結果

問題 No.925 紲星 Extra
ユーザー ei1333333ei1333333
提出日時 2019-11-09 00:14:50
言語 C++17
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 4,595 ms / 10,000 ms
コード長 8,436 bytes
コンパイル時間 3,352 ms
コンパイル使用メモリ 231,448 KB
実行使用メモリ 109,248 KB
最終ジャッジ日時 2023-10-13 05:51:40
合計ジャッジ時間 69,981 ms
ジャッジサーバーID
(参考情報)
judge12 / judge14
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,352 KB
testcase_01 AC 1 ms
4,348 KB
testcase_02 AC 2 ms
4,348 KB
testcase_03 AC 18 ms
4,360 KB
testcase_04 AC 18 ms
4,352 KB
testcase_05 AC 4,164 ms
82,540 KB
testcase_06 AC 4,144 ms
83,052 KB
testcase_07 AC 4,235 ms
82,840 KB
testcase_08 AC 3,965 ms
83,060 KB
testcase_09 AC 3,573 ms
83,312 KB
testcase_10 AC 4,217 ms
66,968 KB
testcase_11 AC 4,389 ms
98,724 KB
testcase_12 AC 3,931 ms
102,596 KB
testcase_13 AC 2,353 ms
82,608 KB
testcase_14 AC 3,501 ms
63,584 KB
testcase_15 AC 2,384 ms
82,808 KB
testcase_16 AC 4,595 ms
83,184 KB
testcase_17 AC 4,020 ms
59,364 KB
testcase_18 AC 4,457 ms
83,576 KB
testcase_19 AC 4,393 ms
57,764 KB
testcase_20 AC 4,245 ms
105,752 KB
testcase_21 AC 2,246 ms
109,248 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>

#pragma GCC optimize ("O3")
#pragma GCC target ("avx")

using namespace std;

using int64 = long long;
const int mod = 1e9 + 7;


const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}

template< class Monoid >
struct RandomizedBinarySearchTree {
  using F = function< Monoid(Monoid, Monoid) >;


  inline int xor128() {
    static int x = 123456789;
    static int y = 362436069;
    static int z = 521288629;
    static int w = 88675123;
    int t;

    t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
  }

  struct Node {
    Node *l, *r;
    int cnt;
    Monoid key, sum;

    Node() = default;

    Node(const Monoid &k) : cnt(1), key(k), sum(k), l(nullptr), r(nullptr) {}
  };

  const Monoid M1;
  const F f;

  RandomizedBinarySearchTree(const F &f, const Monoid &M1) :
      f(f), M1(M1) {}

  inline Node *alloc(const Monoid &key) { return new Node(key); }

  virtual Node *clone(Node *t) { return t; }

  inline int count(const Node *t) { return t ? t->cnt : 0; }

  inline Monoid sum(const Node *t) { return t ? t->sum : M1; }

  inline Node *update(Node *t) {
    t->cnt = count(t->l) + count(t->r) + 1;
    t->sum = f(f(sum(t->l), t->key), sum(t->r));
    return t;
  }

  Node *merge(Node *l, Node *r) {
    if(!l || !r) return l ? l : r;
    if(xor128() % (l->cnt + r->cnt) < l->cnt) {
      l->r = merge(l->r, r);
      return update(l);
    } else {
      r->l = merge(l, r->l);
      return update(r);
    }
  }

  pair< Node *, Node * > split(Node *t, int k) {
    if(!t) return {t, t};
    if(k <= count(t->l)) {
      auto s = split(t->l, k);
      t->l = s.second;
      return {s.first, update(t)};
    } else {
      auto s = split(t->r, k - count(t->l) - 1);
      t->r = s.first;
      return {update(t), s.second};
    }
  }

  Node *build(int l, int r, const vector< Monoid > &v) {
    if(l + 1 >= r) return alloc(v[l]);
    return merge(build(l, (l + r) >> 1, v), build((l + r) >> 1, r, v));
  }

  Node *build(const vector< Monoid > &v) {
    return build(0, (int) v.size(), v);
  }

  void dump(Node *r, typename vector< Monoid >::iterator &it) {
    if(!r) return;
    dump(r->l, it);
    *it = r->key;
    dump(r->r, ++it);
  }

  vector< Monoid > dump(Node *r) {
    vector< Monoid > v((size_t) count(r));
    auto it = begin(v);
    dump(r, it);
    return v;
  }

  string to_string(Node *r) {
    auto s = dump(r);
    string ret;
    for(int i = 0; i < s.size(); i++) ret += ", ";
    return (ret);
  }

  void insert(Node *&t, int k, const Monoid &v) {
    auto x = split(t, k);
    t = merge(merge(x.first, alloc(v)), x.second);
  }

  void erase(Node *&t, int k) {
    auto x = split(t, k);
    t = merge(x.first, split(x.second, 1).second);
  }

  Monoid query(Node *&t, int a, int b) {
    auto x = split(t, a);
    auto y = split(x.second, b - a);
    auto ret = sum(y.first);
    t = merge(x.first, merge(y.first, y.second));
    return ret;
  }

  void set_element(Node *&t, int k, const Monoid &x) {
    if(k < count(t->l)) set_element(t->l, k, x);
    else if(k == count(t->l)) t->key = t->sum = x;
    else set_element(t->r, k - count(t->l) - 1, x);
    t = update(t);
  }


  int size(Node *t) {
    return count(t);
  }

  bool empty(Node *t) {
    return !t;
  }

  Node *makeset() {
    return nullptr;
  }


  int lower_bound(Node *t, const Monoid x) {
    if(!t) return 0;
    if(x <= t->key) return lower_bound(t->l, x);
    return lower_bound(t->r, x) + count(t->l) + 1;
  }

  Monoid lower_bound_sum(Node *t, const Monoid x) {
    if(!t) return 0;
    if(x <= t->key) return lower_bound_sum(t->l, x);
    return lower_bound_sum(t->r, x) + sum(t->l) + t->key;
  }


  Monoid kth_element(Node *t, int k) {
    if(k < count(t->l)) return kth_element(t->l, k);
    if(k == count(t->l)) return t->key;
    return kth_element(t->r, k - count(t->l) - 1);
  }


  void insert_key(Node *&t, const Monoid &x) {
    insert(t, lower_bound(t, x), x);
  }

  void erase_key(Node *&t, const Monoid &x) {
    erase(t, lower_bound(t, x));
  }

};

template< class T >
struct BinaryIndexedTree {
  vector< T > data;

  BinaryIndexedTree(int sz) {
    data.assign(++sz, 0);
  }

  T sum(int k) {
    T ret = 0;
    for(++k; k > 0; k -= k & -k) ret += data[k];
    return (ret);
  }

  void add(int k, T x) {
    for(++k; k < data.size(); k += k & -k) data[k] += x;
  }
};

int main() {
  auto f = [](const int64 &a, const int64 &b) {
    return a + b;
  };
  using RBST = RandomizedBinarySearchTree< int64 >;
  RBST rbst(f, 0LL);

  int N, Q;
  cin >> N >> Q;
  BinaryIndexedTree< int64 > bit(N);


  int sz = 1;
  while(sz < N) sz <<= 1;
  vector< RBST::Node * > seg(2 * sz, nullptr);

  vector< int64 > A(N);
  cin >> A;

  auto add = [&](int k, int64 x) {
    bit.add(k, x);
    k += sz;
    rbst.insert_key(seg[k], x);
    while(k >>= 1) rbst.insert_key(seg[k], x);
  };

  auto erase = [&](int k, int64 x) {
    bit.add(k, -x);
    k += sz;
    rbst.erase_key(seg[k], x);
    while(k >>= 1) rbst.erase_key(seg[k], x);
  };

  auto query1 = [&](int a, int b, int64 x) {
    int64 ret = 0;
    for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if(a & 1) ret += rbst.lower_bound(seg[a++], x);
      if(b & 1) ret += rbst.lower_bound(seg[--b], x);
    }
    return ret;
  };

  auto query2 = [&](int a, int b, int64 x) {
    int64 sum = 0;
    for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if(a & 1) sum += rbst.lower_bound_sum(seg[a++], x);
      if(b & 1) sum += rbst.lower_bound_sum(seg[--b], x);
    }
    return sum;
  };


  for(int i = 0; i < N; i++) {
    add(i, A[i]);
  }

  int64 S = 0;

  while(Q--) {
    int T;
    cin >> T;
    if(T == 1) {
      int64 X, Y;
      cin >> X >> Y;
      X ^= S % (1LL << 16);
      Y ^= S % (1LL << 40);
      --X;
      erase(X, A[X]);
      A[X] = Y;
      add(X, A[X]);

    } else {
      int64 L, R;
      cin >> L >> R;
      L ^= S % (1LL << 16);
      R ^= S % (1LL << 16);
      if(L > R) swap(L, R);
      --L;

      int64 mid = (R - L) / 2;
      int64 mid_val = 0;
      for(int i = 39; i >= 0; i--) {
        if(query1(L, R, mid_val | (1LL << i)) <= mid) mid_val |= 1LL << i;
      }
      ++mid_val;
      int64 low_cnt = query1(L, R, mid_val);
      int64 low_sum = query2(L, R, mid_val);
      --mid_val;

      int64 high_cnt = R - L;
      int64 high_sum = bit.sum(R - 1) - bit.sum(L - 1);
      high_cnt -= low_cnt;
      high_sum -= low_sum;

      int64 ans = high_sum - high_cnt * mid_val + low_cnt * mid_val - low_sum;
      cout << ans << "\n";
      S ^= ans;

    }
  }
}
0