Bzoj 3196 二逼平衡树
树状数组套线段树(值域线段树)记得离散化
# include <bits/stdc++.h>
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(2e5 + 10), __(5e6 + 10), INF(2147483647);
IL ll Read(){
RG char c = getchar(); RG ll x = 0, z = 1;
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
int n, m, qo[_], ql[_], qr[_], qk[_], len, o[_], a[_];
int sz[__], ls[__], rs[__], rt[__], tmp[2][20], cnt, t0, t1;
IL void Modify(RG int &x, RG int l, RG int r, RG int id, RG int v){
if(!x) x = ++cnt; sz[x] += v;
if(l == r) return;
RG int mid = (l + r) >> 1;
if(id <= mid) Modify(ls[x], l, mid, id, v);
else Modify(rs[x], mid + 1, r, id, v);
}
IL void Add(RG int x, RG int v){ for(RG int i = x; i <= n; i += i & -i) Modify(rt[i], 1, len, a[x], v); }
IL int Query(RG int x, RG int l, RG int r, RG int id){
if(l == r) return sz[x];
RG int mid = (l + r) >> 1;
if(id <= mid) return Query(ls[x], l, mid, id);
else return sz[ls[x]] + Query(rs[x], mid + 1, r, id);
}
IL int Rank(RG int l, RG int r, RG int k){
if(l > r) return 0;
RG int sum = 0;
for(RG int i = r; i; i -= i & -i) sum += Query(rt[i], 1, len, k);
for(RG int i = l - 1; i; i -= i & -i) sum -= Query(rt[i], 1, len, k);
return sum;
}
IL int Find_Kth(RG int l, RG int r, RG int k){
if(l == r) return l;
RG int mid = (l + r) >> 1, sum = 0;
for(RG int i = 1; i <= t1; ++i) sum += sz[ls[tmp[1][i]]];
for(RG int i = 1; i <= t0; ++i) sum -= sz[ls[tmp[0][i]]];
if(sum >= k){
for(RG int i = 1; i <= t1; ++i) tmp[1][i] = ls[tmp[1][i]];
for(RG int i = 1; i <= t0; ++i) tmp[0][i] = ls[tmp[0][i]];
return Find_Kth(l, mid, k);
}
else{
for(RG int i = 1; i <= t1; ++i) tmp[1][i] = rs[tmp[1][i]];
for(RG int i = 1; i <= t0; ++i) tmp[0][i] = rs[tmp[0][i]];
return Find_Kth(mid + 1, r, k - sum);
}
}
IL int Kth(RG int l, RG int r, RG int k){
t0 = t1 = 0;
for(RG int i = l - 1; i; i -= i & -i) tmp[0][++t0] = rt[i];
for(RG int i = r; i; i -= i & -i) tmp[1][++t1] = rt[i];
return o[Find_Kth(1, len, k)];
}
int main(RG int argc, RG char* argv[]){
n = Read(); m = Read();
for(RG int i = 1; i <= n; ++i) a[i] = Read(), o[++len] = a[i];
for(RG int i = 1; i <= m; ++i){
qo[i] = Read();
if(qo[i] == 3) ql[i] = qr[i] = Read(), qk[i] = Read();
else ql[i] = Read(), qr[i] = Read(), qk[i] = Read();
if(qo[i] != 2) o[++len] = qk[i];
}
sort(o + 1, o + len + 1); len = unique(o + 1, o + len + 1) - o - 1;
for(RG int i = 1; i <= n; ++i) a[i] = lower_bound(o + 1, o + len + 1, a[i]) - o, Add(i, 1);
for(RG int i = 1; i <= m; ++i){
if(qo[i] == 3){
Add(ql[i], -1);
a[ql[i]] = lower_bound(o + 1, o + len + 1, qk[i]) - o;
Add(ql[i], 1);
}
else if(qo[i] == 1){
qk[i] = lower_bound(o + 1, o + len + 1, qk[i]) - o;
printf("%d\n", Rank(ql[i], qr[i], qk[i] - 1) + 1);
}
else if(qo[i] == 2) printf("%d\n", Kth(ql[i], qr[i], qk[i]));
else if(qo[i] == 4){
qk[i] = lower_bound(o + 1, o + len + 1, qk[i]) - o;
RG int sum = Rank(ql[i], qr[i], qk[i] - 1);
printf("%d\n", Kth(ql[i], qr[i], sum));
}
else{
qk[i] = lower_bound(o + 1, o + len + 1, qk[i]) - o;
RG int sum = Rank(ql[i], qr[i], qk[i]);
printf("%d\n", Kth(ql[i], qr[i], sum + 1));
}
}
return 0;
}