BZOJ 4631: 踩气球
线段树上每个节点开个vector,表示包含当前区间的熊孩子的编号
当一个区间的值变为 \(0\) 时遍历这个vector,对熊孩子的权值减去当前区间原始权值和
当熊孩子的权值变为 \(0\) 时答案加一
vector总共只有 \(O(m \log n)\) 个元素,最多会被遍历一次
所以复杂度还是 \(O(n\log n)\)
#include <bits/stdc++.h>
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) >> 1)
namespace IO {
void read() {}
template<class T, class ... T2>
inline void read(T &x, T2 &... oth) {
x = 0; T f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
x *= f;
read(oth...);
}
}
const int N = 1e5 + 7;
int n, m;
int tree[N << 2], val[N << 2], a[N];
std::vector<int> vec[N << 2];
void build(int p, int l, int r) {
if (l == r) {
IO::read(tree[p]);
val[p] = tree[p];
return;
}
build(lp, l, mid);
build(rp, mid + 1, r);
tree[p] = tree[lp] + tree[rp];
val[p] = val[lp] + val[rp];
}
void update(int p, int l, int r, int x, int y, int id) {
if (x <= l && y >= r) {
vec[p].push_back(id);
a[id] += val[p];
return;
}
if (x <= mid) update(lp, l, mid, x, y, id);
if (y > mid) update(rp, mid + 1, r, x, y, id);
}
int ans;
void update(int p, int l, int r, int pos) {
if (l == r) {
tree[p]--;
if (!tree[p]) {
for (int i = 0; i < vec[p].size(); i++) {
int id = vec[p][i];
a[id] -= val[p];
if (!a[id]) ans++;
}
vec[p].clear();
}
return;
}
if (pos <= mid) update(lp, l, mid, pos);
else update(rp, mid + 1, r, pos);
tree[p] = tree[lp] + tree[rp];
if (!tree[p]) {
for (int i = 0; i < vec[p].size(); i++) {
int id = vec[p][i];
a[id] -= val[p];
if (!a[id]) ans++;
}
vec[p].clear();
}
}
int main() {
IO::read(n, m);
build(1, 1, n);
for (int i = 1; i <= m; i++) {
int l, r;
IO::read(l, r);
update(1, 1, n, l, r, i);
}
int q;
IO::read(q);
for (int x; q--; ) {
IO::read(x);
x = (x + ans - 1) % n + 1;
update(1, 1, n, x);
printf("%d\n", ans);
}
return 0;
}