http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18964
动态求区间第k大,树状数组套主席树,终于会了。还需要多练
感谢博主的代码帮忙
http://www.cnblogs.com/kuangbin/p/3308118.html
真的不好讲,建议学习的直接看代码。
My code
//Hello. I'm Peter.
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
#define N 50010
#define M 10010
#define MAXN 2500010
int n, m, a[N], tot, Tid[N], Uid[N], uid[N];
int temp[N + M], numtemp;
int getemp(int x){
return (int)(lower_bound(temp + 1, temp + 1 + numtemp, x) - temp);
}
struct Oper{
char ty;
int i,j,k,t;
}oper[M];
#define mid ((l+r)>>1)
struct Segment_Tree{
int sum;
int lson, rson;
}tree[MAXN];
int init_big_tree(int l,int r){
int id = tot++;
tree[id].sum = 0;
if(l == r) return id;
tree[id].lson = init_big_tree(l, mid);
tree[id].rson = init_big_tree(mid + 1, r);
return id;
}
int update_tree(int faid,int p,int l,int r,int v){
int id = tot++;
tree[id] = tree[faid];
tree[id].sum += v;
if(l == r) return id;
if(p <= mid) tree[id].lson = update_tree(tree[faid].lson, p, l, mid, v);
else tree[id].rson = update_tree(tree[faid].rson, p, mid + 1, r, v);
return id;
}
int calsum(int p,int nowid){
int ans = 0;
for(int i = p; i>0; i -= i&-i){
int lsid = tree[ uid[i] ].lson;
ans += tree[ lsid ].sum;
}
int lsid = tree[ nowid ].lson;
ans += tree[ lsid ].sum;
return ans;
}
int query_kth(int l,int r,int fr,int to,int frid,int toid,int k){
if(l == r) return l;
int k1 = calsum(to, toid) - calsum(fr, frid);
if(k1 >= k){
for(int i = to; i>0 ; i -= i&-i) uid[i] = tree[ uid[i] ].lson;
for(int i = fr; i>0 ; i -= i&-i) uid[i] = tree[ uid[i] ].lson;
return query_kth(l, mid, fr, to, tree[frid].lson, tree[toid].lson, k);
}
else{
for(int i = to; i>0 ; i -= i&-i) uid[i] = tree[ uid[i] ].rson;
for(int i = fr; i>0 ; i -= i&-i) uid[i] = tree[ uid[i] ].rson;
return query_kth(mid + 1, r, fr, to, tree[frid].rson, tree[toid].rson, k - k1);
}
}
void update(int fr,int to,int v,int val){
for(int i = fr; i <= to; i += i&-i){
Uid[i] = update_tree(Uid[i], v, 1, numtemp, val);
}
}
#define input freopen("/Users/peteryuanpan/data.txt","r",stdin)
int main(){
//input;
int T = read();
for(int kase = 1; kase <= T; kase++){
n = read(), m = read();
numtemp = 0;
for(int i = 1; i <= n; i++){
a[i] = read();
temp[++numtemp] = a[i];
}
for(int i = 1; i <= m; i++){
char tty[10];
scanf("%s",tty);
oper[i].ty = tty[0];
if(tty[0] == 'Q'){
oper[i].i = read(), oper[i].j = read(), oper[i].k = read();
}
else{
oper[i].i = read(), oper[i].t = read();
temp[++numtemp] = oper[i].t;
}
}
sort(temp + 1, temp + 1 + numtemp);
numtemp = (int)(unique(temp + 1, temp + 1 + numtemp) - (temp + 1));
for(int i = 1; i <= n; i++) a[i] = getemp(a[i]);
for(int i = 1; i <= m; i++) if(oper[i].ty == 'C') oper[i].t = getemp(oper[i].t);
tot = 0;
Tid[0] = init_big_tree(1, numtemp);
for(int i = 1; i <= n; i++){
Tid[i] = update_tree(Tid[i-1], a[i], 1, numtemp, +1);
}
for(int i = 1; i <= n; i++){
Uid[i] = Tid[0];
}
for(int im = 1; im <= m; im++){
if(oper[im].ty == 'Q'){
int fr = oper[im].i, to = oper[im].j;
for(int i = fr - 1; i>0; i -= i&-i) uid[i] = Uid[i];
for(int i = to; i>0; i -= i&-i) uid[i] = Uid[i];
int a = query_kth(1, numtemp, fr - 1, to, Tid[fr - 1], Tid[to], oper[im].k);
printf("%d\n",temp[a]);
}
else{
int p = oper[im].i, v = oper[im].t;
update(p, n, a[p], -1);
update(p, n, v, +1);
a[p] = v;
}
}
}
return 0;
}