题解:P13980 数列分块入门 5
Chenyichen0420 · · 题解
思路分析
我们可以老老实实的分块,然后发现又是特殊性质修改类分块。
为什么说是特殊性质修改类呢?因为显然在这道题的数据范围下,一个数是开不了几次根的。
一个较为精确的上界是
于是我们可以考虑分块。边角料直接处理,整块判断一下,如果有
总的时间复杂度上界为
#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define sipt
//#define sopt
struct IO {
#define mxsz (1 << 20)
char buf[mxsz], * p1, * p2;
char pbuf[mxsz], * pp;
IO() : p1(buf), p2(buf), pp(pbuf) {}
~IO() { fwrite(pbuf, 1, pp - pbuf, stdout); }
inline char gc() {
if (p1 == p2) p2 = (p1 = buf) + fread(buf, 1, mxsz, stdin);
return p1 == p2 ? ' ' : *p1++;
}
#ifndef sipt
inline int read() {
int r = 0; char c = gc(); while (c < '0' || c>'9') c = gc();
while (c >= '0' && c <= '9') r = r * 10 + (c ^ 48), c = gc();
return r;
}
#else
inline int read() {
int r = 0; char c = gc(); bool rev = 0;
while (c < '0' || c>'9') rev |= (c == '-'), c = gc();
while (c >= '0' && c <= '9') r = r * 10 + (c ^ 48), c = gc();
return rev ? ~r + 1 : r;
}
#endif
inline void push(const char& c) {
if (pp - pbuf == mxsz) fwrite(pbuf, 1, mxsz, stdout), pp = pbuf;
*pp++ = c;
}
inline void write(int x) {
static char sta[22]; int top = 0;
do sta[top++] = x % 10, x /= 10; while (x);
while (top) push(sta[--top] ^ 48);
}
inline void write(int x, char opc) {
#ifdef sopt
if (x < 0) push('-'), x = ~x + 1;
#endif
write(x), push(opc);
}
} io;
int n, a[300005], sz, sm[300005]; bool alz[300005];
#define blk(i) (i / sz)
inline bool chk(int bl) {
for (int i = bl * sz; i != (bl + 1) * sz && i != n; ++i)
if (a[i] > 1) return 1;
return 0;
}
inline void chg(int l, int r) {
int bl = blk(l), br = blk(r);
if (bl == br) {
if (!alz[bl])return;
for (int i = l; i <= r; ++i)
sm[bl] -= a[i],
a[i] = sqrt(a[i]),
sm[bl] += a[i];
alz[bl] = chk(bl);
return;
}
if (alz[bl]) {
for (int i = l; i != sz * (bl + 1); ++i)
sm[bl] -= a[i],
a[i] = sqrt(a[i]),
sm[bl] += a[i];
alz[bl] = chk(bl);
}
if (alz[br]) {
for (int i = br * sz; i <= r; ++i)
sm[br] -= a[i],
a[i] = sqrt(a[i]),
sm[br] += a[i];
alz[br] = chk(br);
}
for (int j = bl + 1; j != br; ++j) {
if (alz[j]) {
for (int i = j * sz; i != (j + 1) * sz; ++i)
sm[j] -= a[i],
a[i] = sqrt(a[i]),
sm[j] += a[i];
alz[j] = chk(j);
}
}
}
inline int que(int l, int r) {
int bl = blk(l), br = blk(r), ret = 0;
if (bl == br) {
for (int i = l; i <= r; ++i) ret += a[i];
return ret;
}
for (int i = l; i != sz * (bl + 1); ++i) ret += a[i];
for (int i = br * sz; i <= r; ++i) ret += a[i];
for (int j = bl + 1; j != br; ++j) ret += sm[j];
return ret;
}
signed main() {
ios::sync_with_stdio(0);
sz = sqrt(n = io.read());
for (int i = 0; i != n; ++i)
sm[blk(i)] += (a[i] = io.read()),
alz[blk(i)] |= (a[i] > 1);
for (int i = 1, o, l, r, v; i <= n; ++i) {
if (o = io.read(), l = io.read() - 1, r = io.read() - 1, o)
io.write(que(l, r), '\n');
else chg(l, r);
}
}