题解:P13983 数列分块入门 8
Chenyichen0420 · · 题解
思路分析
其实这道题可能用 ODT 会是更好的选择,不过尊重分块。
我们考虑一下分块的惯用套路:序列分段,暴力边角,高速整块。
我们思考一种疑似可行的策略:
如果一个整块内的元素是同一个,那么可以
随后,我们仍然暴力修改边角,中间的部分我们标记为同一个元素。
为什么说是疑似可行呢?单次显然可以卡到
我们选择费用预支分析。要想让一个块被暴力处理,要么是散块,要么是不一致的整块。
不一致的整块只能由散块修改贡献出来。因此我们考虑在修改散块时直接将时间复杂度乘二,后面直接将中间的整块视为元素一致,可以视为
那显然每一步的时间复杂度都是严格的
#include<bits/stdc++.h>
using namespace std;
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, tv[300005];
#define blk(i) (i / sz)
inline void pia(int p) {
if (tv[p] == -1) return;
for (int i = p * sz; i != (p + 1) * sz; ++i)
a[i] = tv[p];
tv[p] = -1;
}
signed main() {
ios::sync_with_stdio(0);
sz = sqrt(n = io.read()) * 0.5; memset(tv, -1, sizeof tv);
for (int i = 0; i != n; ++i) a[i] = io.read();
for (int i = 1, l, r, c; i <= n; ++i) {
l = io.read() - 1, r = io.read() - 1, c = io.read();
int bl = blk(l), br = blk(r), ans = 0;
if (bl == br) {
pia(bl);
for (int i = l; i <= r; ++i)
a[i] != c ? a[i] = c : ans++;
io.write(ans, '\n');
continue;
}
pia(bl); pia(br);
for (int i = l; i != (bl + 1) * sz; ++i)
a[i] != c ? a[i] = c : ans++;
for (int i = br * sz; i <= r; ++i)
a[i] != c ? a[i] = c : ans++;
for (int i = bl + 1; i < br; ++i)
if (tv[i] != -1)
if (tv[i] != c) tv[i] = c;
else ans += sz;
else {
for (int j = i * sz; j != (i + 1) * sz; ++j)
a[j] != c ? a[j] = c : ans++;
tv[i] = c;
}
io.write(ans, '\n');
}
}