有修改的区间第K大数
惭愧啊,到现在才做到这道题,这道题公认有两种做法,一种是树状数组+主席树,遗憾地说我不会……
另外一种是线段树套平衡树,我用的是这种方法,只要线段树每一个节点都是一棵平衡树,我们就可以对序列进行动态修改了。
代码上,主代码部分和线段树部分我写的,treap参照了silver__bullet的代码,为防止内存开销过大,采用动态建树,恰好我不会指针……
//BZOJ上面A的……
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf = ~0u >> 1;
const int N = (int)1e5 + 10;
const int maxn = (int)1e9 + 1;
#define lson l, m, n << 1
#define rson m + 1, r, n << 1 | 1
int x[N], n, m;
struct Treap{
struct node{
node *ch[2];
int v, p, sz;
node(int _v, node *n):
v(_v){ch[0] = ch[1] = n; p = rand(); sz = 1;}
void update(){sz = ch[0]->sz + ch[1]->sz + 1;}
};
node *root, *null;
Treap(){
}
void init(){
null = new node(0, 0); null->sz = 0; null->p = inf;
null->ch[0] = null->ch[1] = null;
root = null;
}
void rotate(node *&t, bool d){
node *_t = t->ch[d];
t->ch[d] = _t->ch[!d];
_t->ch[!d] = t;
_t->update();
t->update();
t = _t;
}
void __insert(node *&t, int val){
if (t == null){
t = new node(val, null);
return;
}
bool d = val > t->v;
__insert(t->ch[d], val);
if (t->ch[d]->p < t->p) rotate(t, d);
t->update();
}
void __del(node *&t, int val){
if (t == null) return;
if (val == t->v){
bool d = t->ch[1]->p < t->ch[0]->p;
if (t->ch[d] == null){
delete t;
t = null;
return;
}
rotate(t, d);
__del(t->ch[!d], val);
}else{
bool d = val > t->v;
__del(t->ch[d], val);
}
t->update();
}
int __rank(node *t, int val){
if (t == null) return 0;
int num = t->ch[0]->sz;
if (val < t->v) return __rank(t->ch[0], val);
return num + 1 + __rank(t->ch[1], val);
}
void __show(node *x){
if (x == null) return;
__show(x->ch[0]);
printf("%d ", x->v);
__show(x->ch[1]);
}
void insert(int val){
__insert(root, val);
}
void del(int val){
__del(root, val);
}
int rank(int val){
return __rank(root, val);
}
void show(){
__show(root);
puts("");
}
void __fre(node *t){
if (t == null) return;
__fre(t->ch[0]);
__fre(t->ch[1]);
delete t;
}
void fre(){
__fre(root);
}
};
struct segtree{
Treap s[N << 2];
void build(int l, int r, int n){
s[n].init();
for (int i = l; i <= r; i++)
s[n].insert(x[i]);
if (l == r) return;
int m = (l + r) >> 1;
build(lson);
build(rson);
}
void del(int l, int r, int n){
s[n].fre();
if (l == r) return;
int m = (l + r) >> 1;
del(lson);
del(rson);
}
void update(int nn, int a, int l, int r, int n){
s[n].del(x[nn]);
s[n].insert(a);
if (l == r) return;
int m = (l + r) >> 1;
if (nn <= m) update(nn, a, lson);
else update(nn, a, rson);
}
int query(int ll, int rr, int val, int l, int r, int n){
if (ll == l && rr == r){
return s[n].rank(val);
}
int m = (l + r) >> 1;
if (rr <= m) return query(ll, rr, val, lson);
else if (ll > m) return query(ll, rr, val, rson);
else return query(ll, m, val, lson) + query(m + 1, rr, val, rson);
}
};
segtree T;
int check(int L, int R, int val, int k){
int a = T.query(L, R, val - 1, 1, n, 1);
int b = T.query(L, R, val, 1, n, 1);
if (k > a && k <= b) return 1;
if (k <= a) return 0;
if (k > b) return -1;
}
int bs(int l, int r, int L, int R, int k){
while(l <= r){
int m = (l + r) >> 1;
int res = check(L, R, m, k);
if (res == 1) return m;
else if (res == -1) l = m + 1;
else r = m - 1;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in", "rt", stdin);
#endif
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &x[i]);
T.build(1, n, 1);
char op[5]; int l, r, k;
while(m--){
scanf("%s", op);
if (op[0] == 'Q'){
scanf("%d%d%d", &l, &r, &k);
int ans = bs(0, maxn, l, r, k);
printf("%d\n", ans);
}else{
scanf("%d%d", &l, &r);
T.update(l, r, 1, n, 1);
x[l] = r;
}
}
T.del(1, n, 1);
return 0;
}