P7492 题解
单根号锤了 std 的俩
考虑分块,把原序列分成
对于
对于 continue 掉这个块即可。
接下来是复杂度分析,考虑到一个块最多被有效操作
void Up(int x) {
int b = bl[x];
yu[b] = -1, isum[b] = lsum[b] = rsum[b] = sum[b] = 0;
rep (i, lbl[x], rbl[x])
yu[b] &= a[i], sum[b] += a[i], up(lsum[b], sum[b]);
ll s = 0;
per (i, rbl[x], lbl[x])
s += a[i], up(rsum[b], s);
s = 0;
rep (i, lbl[x], rbl[x])
s += a[i], up(s, 0), up(isum[b], s);
}
void Init() {
sz = sqrt(n);
re (i, n)
bl[i] = (i - 1) / sz + 1, lbl[i] = (bl[i] - 1) * sz + 1, rbl[i] = min(n, bl[i] * sz);
ste(i, 1, n, sz) Up(i);
}
void Or(int l, int r, int x) {
if (bl[l] == bl[r]) {
rep (i, l, r)
a[i] |= x;
Up(l);
return;
}
Or(l, rbl[l], x);
ste(i, lbl[l] + sz, rbl[r] - sz, sz) {
int b = bl[i];
if ((yu[b] & x) != x) Or(lbl[i], rbl[i], x);
}
Or(lbl[r], r, x);
}
ll Ask(int l, int r) {
ll ans = 0, s = 0, ss = 0;
if (bl[l] == bl[r]) {
rep (i, l, r)
s += a[i], up(s, 0), up(ans, s);
return ans;
}
rep (i, l, rbl[l])
s += a[i], up(s, 0), up(ans, s);
s = 0;
per (i, rbl[l], l)
s += a[i], up(ss, s);
rep (b, bl[l] + 1, bl[r] - 1)
up(ans, ss + lsum[b]), ss += sum[b], up(ss, rsum[b]), up(ans, ss), up(ans, isum[b]);
s = 0;
rep (i, lbl[r], r)
s += a[i], up(s, 0), up(ans, s), ss += a[i], up(ans, ss);
return ans;
}