QOJ6608 Descent of Dragons
修改只会使值从 \(x\) 变成 \(x+1\),这个对整体的值域变化是非常小的。
对于一个阈值 \(lim\),考虑 \(01\) 序列 \(A_{lim}\),\(A_{lim,i}=[a_i\ge lim]\)。
对于一次修改,实际上就是让 \(A_{x+1,i}\leftarrow A_{x+1,i}\ \mathrm{or}\ A_{x,i}\)。
这个 \(\mathrm{or}\) 不好维护,但是可以发现 \(A_{x+1,i}\) 总是 \(\le A_{x,i}\) 的,所以只要直接复制就做完了。而这个是可以线段树维护的。
#include <bits/stdc++.h>
using namespace std;
const int kN = 5e5 + 5, kS = kN * 60;
int n, q;
struct SGT {
int tot = 0;
int root[kN];
int ls[kS], rs[kS], cnt[kS];
int Copy(int x) {
int p = ++tot;
ls[p] = ls[x];
rs[p] = rs[x];
cnt[p] = cnt[x];
return p;
}
void Up(int o) { cnt[o] = cnt[ls[o]] + cnt[rs[o]]; }
void Build(int &o, int l, int r) {
cnt[o = ++tot] = r - l + 1;
if(l == r) return ;
int mid = (l + r) >> 1;
Build(ls[o], l, mid);
Build(rs[o], mid + 1, r);
}
void Copy(int &o1, int o2, int l, int r, int x, int y) {
if(!o2 || (l > y) || (r < x)) return ;
if((l >= x) && (r <= y)) return void(o1 = o2);
int mid = (l + r) >> 1;
o1 = Copy(o1);
Copy(ls[o1], ls[o2], l, mid, x, y);
Copy(rs[o1], rs[o2], mid + 1, r, x, y);
Up(o1);
}
bool Count(int o, int l, int r, int x, int y) {
if(!o || (l > y) || (r < x)) return 0;
if((l >= x) && (r <= y)) return cnt[o];
int mid = (l + r) >> 1;
return Count(ls[o], l, mid, x, y) || Count(rs[o], mid + 1, r, x, y);
}
} sgt;
int main() {
// freopen("1.in", "r", stdin);
// freopen("1.out", "w", stdout);
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> q;
sgt.Build(sgt.root[0], 1, n);
while(q--) {
int op, l, r, x;
cin >> op >> l >> r;
if(op == 1) {
cin >> x;
sgt.Copy(sgt.root[x + 1], sgt.root[x], 1, n, l, r);
}else {
int L = -1, R = kN;
while(L + 1 < R) {
int mid = (L + R) >> 1;
sgt.Count(sgt.root[mid], 1, n, l, r) ? (L = mid) : (R = mid);
}
cout << L << "\n";
}
}
return 0;
}
浙公网安备 33010602011771号