主席树:动态 Kth
1 /*zoj2112 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 2 动态 kth 3 每一棵线段树是维护每一个序列前缀的值在任意区间的个数, 4 如果还是按照静态的来做的话,那么每一次修改都要遍历O(n)棵树, 5 时间就是O(2*M*nlogn)->TLE 6 考虑到前缀和,我们通过树状数组来优化,即树状数组套主席树, 7 每个节点都对应一棵主席树,那么修改操作就只要修改logn棵树, 8 o(nlognlogn+Mlognlogn)时间是可以的, 9 但是直接建树要nlogn*logn(10^7)会MLE 10 我们发现对于静态的建树我们只要nlogn个节点就可以了, 11 而且对于修改操作,只是修改M次,每次改变俩个值(减去原先的,加上现在的) 12 也就是说如果把所有初值都插入到树状数组里是不值得的, 13 所以我们分两部分来做,所有初值按照静态来建,内存O(nlogn), 14 而修改部分保存在树状数组中,每次修改logn棵树,每次插入增加logn个节点 15 O(M*logn*logn+nlogn) 16 17 18 */ 19 #include<cstdio> 20 #include<cstring> 21 #include<cstdlib> 22 #include<iostream> 23 #include<algorithm> 24 #include<vector> 25 #include<cmath> 26 #define ls(i) T[i].ls 27 #define rs(i) T[i].rs 28 #define w(i) T[i].w 29 #define Find(i) (lower_bound(LX.begin(),LX.begin()+n1,i)-LX.begin())+1 30 31 using namespace std; 32 const int N=60000+10; 33 struct node{ 34 int ls,rs,w; 35 node(){ls=rs=w=0;} 36 }T[2000000]; 37 struct ope{ 38 int i,l,r,k; 39 }op[11000]; 40 vector<int> LX,Q1,Q2; 41 int n,n1,m,cnt; 42 int a[61000],root[61000*2]; 43 inline int lowbit(int x){ 44 return x&-x; 45 } 46 void build(int &i,int l,int r,int x){ 47 T[++cnt]=T[i]; i=cnt; 48 w(i)++; 49 if (l==r) return; 50 int m=(l+r)>>1; 51 if (x<=m) build(ls(i),l,m,x); 52 else build(rs(i),m+1,r,x); 53 } 54 void ins(int &i,int l,int r,int x,int v){ 55 if (i==0){ T[++cnt]=T[i]; i=cnt; } 56 w(i)+=v; 57 if (l==r) return; 58 int m=(l+r)>>1; 59 if (x<=m) ins(ls(i),l,m,x,v); 60 else ins(rs(i),m+1,r,x,v); 61 } 62 void my_ins(int pos,int x,int v){ 63 int t=Find(x); 64 for (int i=pos;i<=n;i+=lowbit(i)){ 65 ins(root[i],1,n1,t,v); 66 } 67 } 68 int Qy(vector<int> Q1,vector<int> Q2,int l,int r,int k){ 69 if (l==r) return l; 70 int c=0; 71 int m=(l+r)>>1; 72 for (int i=0;i<Q1.size();i++) c-=w(ls(Q1[i])); 73 for (int i=0;i<Q2.size();i++) c+=w(ls(Q2[i])); 74 for (int i=0;i<Q1.size();i++) Q1[i]=(c>=k?ls(Q1[i]):rs(Q1[i])); 75 for (int i=0;i<Q2.size();i++) Q2[i]=(c>=k?ls(Q2[i]):rs(Q2[i])); 76 77 if (c>=k) return Qy(Q1,Q2,l,m,k); 78 else return Qy(Q1,Q2,m+1,r,k-c); 79 } 80 void query(int l,int r,int k){ 81 Q1.clear();Q2.clear(); 82 Q1.push_back(root[l!=1?l-1+n:0]); 83 Q2.push_back(root[r+n]); 84 for (int i=l-1;i>0;i-=lowbit(i)) Q1.push_back(root[i]); 85 for (int i=r;i>0;i-=lowbit(i)) Q2.push_back(root[i]); 86 87 int t=Qy(Q1,Q2,1,n1,k); 88 printf("%d\n",LX[t-1]); 89 } 90 void work(){ 91 cnt=0; 92 //for (int i=0;i<n1;i++) cout<<list[i]<<" ";cout<<endl; 93 memset(root,0,sizeof(root)); 94 for (int i=1;i<=n;i++){ 95 root[i+n]=root[i-1+n]; 96 int t=Find(a[i]); 97 build(root[i+n],1,n1,t); 98 } 99 for (int i=0;i<m;i++){ 100 if (op[i].i==0){ 101 query(op[i].l,op[i].r,op[i].k); 102 // cout<<"*** "<<i<<endl; 103 }else{ 104 my_ins(op[i].l,a[op[i].l],-1); 105 my_ins(op[i].l,op[i].r,1); 106 a[op[i].l]=op[i].r; 107 } 108 } 109 110 } 111 int main(){ 112 int Cas;scanf("%d",&Cas); 113 while (Cas--){ 114 scanf("%d%d",&n,&m); 115 LX.clear(); 116 for (int i=1;i<=n;i++){ 117 scanf("%d",&a[i]);LX.push_back(a[i]); 118 } 119 char s[10]; 120 for (int i=0;i<m;i++){ 121 scanf("%s",s); 122 if (s[0]=='Q'){ 123 op[i].i=0; 124 scanf("%d%d%d",&op[i].l,&op[i].r,&op[i].k); 125 }else{ 126 op[i].i=1; 127 scanf("%d%d",&op[i].l,&op[i].r); 128 LX.push_back(op[i].r); 129 } 130 } 131 sort(LX.begin(),LX.end()); 132 n1=unique(LX.begin(),LX.end())-LX.begin(); 133 work(); 134 } 135 136 137 return 0; 138 }