結果
| 問題 | No.3671 Reusable Lazy Segment Tree |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-08-27 16:18:45 |
| 言語 | C++23 (gcc 15.3.0 + boost 1.92.0 + ACL) |
| 結果 |
AC
不安定
|
| 実行時間 | 5,939 ms / 6,000 ms |
| + 483µs | |
| コード長 | 8,083 bytes |
| 記録 | |
| コンパイル時間 | 2,673 ms |
| コンパイル使用メモリ | 361,496 KB |
| 実行使用メモリ | 78,096 KB |
| 最終ジャッジ日時 | 2026-09-04 23:01:38 |
| 合計ジャッジ時間 | 35,604 ms |
|
ジャッジサーバーID (参考情報) |
judge3_0 / judge1_0 |
| 外部呼び出し有り |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 19 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
template <class S,
auto op,
auto e,
class F,
auto mapping,
auto composition,
auto id>
struct lazy_segtree {
static_assert(std::is_convertible_v<decltype(op), std::function<S(S, S)>>,
"op must work as S(S, S)");
static_assert(std::is_convertible_v<decltype(e), std::function<S()>>,
"e must work as S()");
static_assert(
std::is_convertible_v<decltype(mapping), std::function<S(F, S)>>,
"mapping must work as F(F, S)");
static_assert(
std::is_convertible_v<decltype(composition), std::function<F(F, F)>>,
"compostiion must work as F(F, F)");
static_assert(std::is_convertible_v<decltype(id), std::function<F()>>,
"id must work as F()");
public:
lazy_segtree() : lazy_segtree(0) {}
explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
explicit lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
size = bit_ceil((unsigned int)(_n));
log = countr_zero((unsigned int)size);
d = std::vector<S>(2 * size, e());
lz = std::vector<F>(size, id());
for (int i = 0; i < _n; i++) d[size + i] = v[i];
dL.assign(2 * size, 0);
lzL.assign(size, 0);
for (int i = size - 1; i >= 1; i--) {
update(i);
}
}
void set(int p, S x) {
assert(0 <= p && p < _n);
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
save_d(p);
d[p] = x;
for (int i = 1; i <= log; i++) update(p >> i);
}
S get(int p) {
assert(0 <= p && p < _n);
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
return d[p];
}
S prod(int l, int r) {
assert(0 <= l && l <= r && r <= _n);
if (l == r) return e();
l += size;
r += size;
for (int i = log; i >= 1; i--) {
if (((l >> i) << i) != l) push(l >> i);
if (((r >> i) << i) != r) push((r - 1) >> i);
}
S sml = e(), smr = e();
while (l < r) {
if (l & 1) sml = op(sml, d[l++]);
if (r & 1) smr = op(d[--r], smr);
l >>= 1;
r >>= 1;
}
return op(sml, smr);
}
S all_prod() { return d[1]; }
void apply(int p, F f) {
assert(0 <= p && p < _n);
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
save_d(p);
d[p] = mapping(f, d[p]);
for (int i = 1; i <= log; i++) update(p >> i);
}
void apply(int l, int r, F f) {
assert(0 <= l && l <= r && r <= _n);
if (l == r) return;
l += size;
r += size;
for (int i = log; i >= 1; i--) {
if (((l >> i) << i) != l) push(l >> i);
if (((r >> i) << i) != r) push((r - 1) >> i);
}
{
int l2 = l, r2 = r;
while (l < r) {
if (l & 1) all_apply(l++, f);
if (r & 1) all_apply(--r, f);
l >>= 1;
r >>= 1;
}
l = l2;
r = r2;
}
for (int i = 1; i <= log; i++) {
if (((l >> i) << i) != l) update(l >> i);
if (((r >> i) << i) != r) update((r - 1) >> i);
}
}
template <bool (*g)(S)> int max_right(int l) {
return max_right(l, [](S x) { return g(x); });
}
template <class G> int max_right(int l, G g) {
assert(0 <= l && l <= _n);
assert(g(e()));
if (l == _n) return _n;
l += size;
for (int i = log; i >= 1; i--) push(l >> i);
S sm = e();
do {
while (l % 2 == 0) l >>= 1;
if (!g(op(sm, d[l]))) {
while (l < size) {
push(l);
l = (2 * l);
if (g(op(sm, d[l]))) {
sm = op(sm, d[l]);
l++;
}
}
return l - size;
}
sm = op(sm, d[l]);
l++;
} while ((l & -l) != l);
return _n;
}
template <bool (*g)(S)> int min_left(int r) {
return min_left(r, [](S x) { return g(x); });
}
template <class G> int min_left(int r, G g) {
assert(0 <= r && r <= _n);
assert(g(e()));
if (r == 0) return 0;
r += size;
for (int i = log; i >= 1; i--) push((r - 1) >> i);
S sm = e();
do {
r--;
while (r > 1 && (r % 2)) r >>= 1;
if (!g(op(d[r], sm))) {
while (r < size) {
push(r);
r = (2 * r + 1);
if (g(op(d[r], sm))) {
sm = op(d[r], sm);
r--;
}
}
return r + 1 - size;
}
sm = op(d[r], sm);
} while ((r & -r) != r);
return 0;
}
void save() {
for (auto[i, v] : dH) dL[i] = 0;
for (auto[i, v] : lzH) lzL[i] = 0;
dH.clear();
lzH.clear();
}
void roll_back() {
for (auto[i, v] : dH) d[i] = v, dL[i] = 0;
for (auto[i, v] : lzH) lz[i] = v, lzL[i] = 0;
dH.clear();
lzH.clear();
}
private:
int _n, size, log;
std::vector<S> d;
std::vector<F> lz;
vector<pair<int,S>> dH;
vector<pair<int,F>> lzH;
vector<short> dL, lzL;
void save_d(int k) {
if (!dL[k]) {
dL[k] = 1;
dH.emplace_back(k, d[k]);
}
}
void save_lz(int k) {
if (!lzL[k]) {
lzL[k] = 1;
lzH.emplace_back(k, lz[k]);
}
}
void update(int k) {
save_d(k);
d[k] = op(d[2 * k], d[2 * k + 1]);
}
void all_apply(int k, F f) {
save_d(k);
d[k] = mapping(f, d[k]);
if (k < size) {
save_lz(k);
lz[k] = composition(f, lz[k]);
}
}
void push(int k) {
all_apply(2 * k, lz[k]);
all_apply(2 * k + 1, lz[k]);
save_lz(k);
lz[k] = id();
}
};
struct S {
int cnt[32] = {0};
int l = 0;
};
S op(const S& x, const S& y) {
S res;
res.l = x.l + y.l;
for (int k = 0; k < 32; k++) res.cnt[k] = x.cnt[k] + y.cnt[k];
return res;
}
S e() {
return S();
}
using ull = unsigned long long;
S mpp(ull f,const S& x) {
S res = x;
for (int k = 0; k < 32; k++) {
if ((f >> k) & 1) res.cnt[k] = 0;
else if ((f >> (k + 30)) & 1) res.cnt[k] = x.l;
}
return res;
}
ull cmpo(ull f, ull g) {
ull e = 0x3FFFFFFF ^ (f >> 30) ^ (f & 0x3FFFFFFF);
return (f & 0x3FFFFFFF) | (g & 0x3FFFFFFF & e) | (((f >> 30) | ((g >> 30) & e)) << 30);
}
ull id() {
return 0;
}
int main(){
int N, M;
cin >> N >> M;
vector<int> A(N), l(M), r(M), x(M), L(M), R(M);
for (auto&v : A) cin >> v;
for (auto&v : l) cin >> v;
for (auto&v : r) cin >> v;
for (auto&v : x) cin >> v;
for (auto&v : L) cin >> v;
for (auto&v : R) cin >> v;
int Q;
cin >> Q;
lazy_segtree<S, op, e, ull, mpp, cmpo, id> seg(N);
for (int i = 0; i < N; i++) {
S r;
r.l = 1;
for (int j = 0; j < 30; j++) r.cnt[j] = (A[i] >> j) & 1;
seg.set(i, r);
}
seg.save();
for (int i = 1; i <= Q; i++) {
int s, q;
cin >> s >> q;
int y = i;
for (int j = 1; j <= q; j++) {
int z = (s + j) % M;
int u = min(N, max(1, l[z] ^ y));
int v = min(N, max(1, r[z] ^ y));
int U = min(N, max(1, L[z] ^ y));
int V = min(N, max(1, R[z] ^ y));
if(u>v)swap(u,v);
if(U>V)swap(U,V);
u--; U--;
ull w = x[z] ^ y;
if (z & 1) seg.apply(u, v, w << 30);
else seg.apply(u, v, 0x3FFFFFFF ^ w);
auto pr = seg.prod(U, V);
y = 0;
for (int k = 0; k < 30; k++) {
y += (ull(pr.cnt[k]) << k) & 0x3FFFFFFF;
y &= 0x3FFFFFFF;
}
}
cout << y << '\n';
seg.roll_back();
}
return 0;
}