The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They have developed a more powerful system such that for N numbers a[1], a[2], ..., a[N], you can ask it like: what is the k-th smallest number of a[i], a[i+1], ..., a[j]? (For some i<=j, 0<k<=j+1-i that you have given to it). More powerful, you can even change the value of some a[i], and continue to query, all the same.
Your task is to write a program for this computer, which
- Reads N numbers from the input (1 <= N <= 50,000)
- Processes M instructions of the input (1 <= M <= 10,000). These instructions include querying the k-th smallest number of a[i], a[i+1], ..., a[j] and change some a[i] to t.
Input
The first line of the input is a single number X (0 < X <= 4), the number of the test cases of the input. Then X blocks each represent a single test case.
The first line of each block contains two integers N and M, representing N numbers and M instruction. It is followed by N lines. The (i+1)-th line represents the number a[i]. Then M lines that is in the following format
Q i j k or
C i t
It represents to query the k-th number of a[i], a[i+1], ..., a[j] and change some a[i] to t, respectively. It is guaranteed that at any time of the operation. Any number a[i] is a non-negative integer that is less than 1,000,000,000.
There're NO breakline between two continuous test cases.
Output
For each querying operation, output one integer to represent the result. (i.e. the k-th smallest number of a[i], a[i+1],..., a[j])
There're NO breakline between two continuous test cases.
Sample Input
2
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
3
6
3
6
题意:给你一个长为n的区间,有m个询问和修改,每次把下标i对应的值改变,或者询问某段区间的第k小值。
思路:这题是很经典的题,可以用主席树和树套树做,对于树套树的做法,我是用线段树的每一个节点都存一个treap,然后每一次修改就是单点更新,修改的时间复杂度为O(n*logn*logn),询问时,需要二分值val,并统计线段树中对应的区间小于val值的个数,询问的时间复杂度为O(n*logn*logn*logn),所以总的时间复杂度为O(n*logn*logn*logn),同时因为线段树最多有logn层,每层都是n个节点,所以treap的空间复杂度为O(n*logn).
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<string> #include<bitset> #include<algorithm> using namespace std; #define lson th<<1 #define rson th<<1|1 typedef long long ll; typedef long double ldb; #define inf 99999999 #define pi acos(-1.0) #define maxn 50005 int rt[maxn*4],a[maxn],n; int cnt; struct Treap{ int key,pri,siz,num,son[2]; void newnode(int x,int y){ key=x;pri=y; siz=num=1; son[0]=son[1]=0; } }T[20*maxn]; void rotate(int p,int &x) { int y=T[x].son[!p]; T[x].siz=T[x].siz-T[y].siz+T[T[y].son[p] ].siz; T[x].son[!p]=T[y].son[p]; T[y].siz=T[y].siz-T[T[y].son[p] ].siz+T[x].siz; T[y].son[p]=x; x=y; } void charu(int key,int &x) { if(x==0){ x=++cnt; T[x].newnode(key,rand()); } else{ T[x].siz++; if(T[x].key==key){ T[x].num++;return; } int p=key<T[x].key; charu(key,T[x].son[!p]); if(T[x].pri<T[T[x].son[!p] ].pri ) rotate(p,x); } } void del(int key, int &x) { if(T[x].key == key) { if(T[x].num>1){ T[x].siz--; T[x].num--; return; } if(T[x].son[0] && T[x].son[1]) { int p=T[T[x].son[0]].pri>T[T[x].son[1]].pri; rotate(p,x); del(key,x); } else x=T[x].son[1]+T[x].son[0]; } else { T[x].siz--; int p=T[x].key>key; del(key,T[x].son[!p]); } } int query_rank(int key,int &x) { if(x==0)return 0; if(T[x].key==key)return T[T[x].son[0] ].siz; if(T[x].key>key)return query_rank(key,T[x].son[0]); if(T[x].key<key)return T[T[x].son[0] ].siz+T[x].num+query_rank(key,T[x].son[1]); } void update(int idx,int val,int L,int R,int th,int f) { if(f)del(a[idx],rt[th]); charu(val,rt[th]); if(L==idx && R==idx){ a[idx]=val; return; } int mid=(L+R)/2; if(idx<=mid)update(idx,val,L,mid,lson,f); else update(idx,val,mid+1,R,rson,f); } int question(int l,int r,int val,int L,int R,int th) { int mid; if(l==L && r==R){ return query_rank(val,rt[th]); } mid=(L+R)/2; if(r<=mid)return question(l,r,val,L,mid,lson); else if(l>mid)return question(l,r,val,mid+1,R,rson); else return question(l,mid,val,L,mid,lson)+question(mid+1,r,val,mid+1,R,rson); } int main() { int m,i,j,Tcase,l,r,c,d,e,mid; char s[10]; scanf("%d",&Tcase); while(Tcase--) { memset(rt,0,sizeof(rt)); scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ scanf("%d",&a[i]); } cnt=0; for(i=1;i<=n;i++){ update(i,a[i],1,n,1,0); } for(i=1;i<=m;i++){ scanf("%s",s); if(s[0]=='C'){ scanf("%d%d",&c,&d); update(c,d,1,n,1,1); } else{ scanf("%d%d%d",&c,&d,&e); l=0;r=1000000000; while(l<=r){ mid=(l+r)/2; //printf("%d %d %d\n",l,r,mid); if(question(c,d,mid,1,n,1)>=e)r=mid-1; else l=mid+1; } printf("%d\n",r); } } } return 0; } /* 2 5 3 3 2 1 4 7 Q 1 4 3 C 2 6 Q 2 5 3 5 3 3 2 1 4 7 Q 1 4 3 C 2 6 Q 2 5 3 */
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<string> #include<bitset> #include<algorithm> using namespace std; typedef long long ll; typedef long double ldb; #define lth th<<1 #define rth th<<1|1 #define inf 99999999 #define pi acos(-1.0) #define maxn 60005 #define M 2500010 int a[maxn],n; struct node{ int l,r,kind,d; }ques[10005]; int pos[maxn],T[maxn],S[maxn]; int lson[M],rson[M],c[M]; int th,tot; int build(int l,int r) { int newroot=++th,i,j,mid; c[newroot]=0; //!!! if(l!=r){ mid=(l+r)/2; lson[newroot]=build(l,mid); rson[newroot]=build(mid+1,r); } return newroot; } int update(int root,int zhi,int value) { int i,j; int newroot=++th;int tmp=newroot; int l=1,r=tot,mid; c[newroot]=c[root]+value; while(l<r){ mid=(l+r)/2; if(zhi<=mid){ r=mid; lson[newroot ]=++th;rson[newroot]=rson[root]; newroot=lson[newroot];root=lson[root]; } else{ l=mid+1; lson[newroot ]=lson[root];rson[newroot]=++th; newroot=rson[newroot];root=rson[root]; } c[newroot]=c[root]+value; } return tmp; } int lowbit(int x) { return x&(-x); } void modify(int pos,int zhi,int value) { int i,j; while(pos<=n){ S[pos]=update(S[pos],zhi,value); pos+=lowbit(pos); } } int use[maxn]; int getsum(int pos) { int sum=0; while(pos>0){ sum+=c[lson[use[pos] ] ]; pos-=lowbit(pos); } return sum; } int question(int left,int right,int k) { int i,j,root1,root2; int l=1,r=tot,mid; for(i=left-1;i>0;i-=lowbit(i))use[i]=S[i]; for(i=right;i>0;i-=lowbit(i))use[i]=S[i]; root1=T[left-1];root2=T[right]; while(l<r){ mid=(l+r)/2; int tmp=getsum(right)-getsum(left-1)+c[lson[root2] ]-c[lson[root1] ]; if(tmp>=k){ r=mid; root1=lson[root1];root2=lson[root2]; for(i=left-1;i>0;i-=lowbit(i))use[i]=lson[use[i] ]; for(i=right;i>0;i-=lowbit(i))use[i]=lson[use[i] ]; } else{ k-=tmp; l=mid+1; root1=rson[root1];root2=rson[root2]; for(i=left-1;i>0;i-=lowbit(i))use[i]=rson[use[i] ]; for(i=right;i>0;i-=lowbit(i))use[i]=rson[use[i] ]; } } return l; } int main() { int m,i,j,Tcase,c,d,e; char str[5]; scanf("%d",&Tcase); while(Tcase--) { scanf("%d%d",&n,&m); tot=0; for(i=1;i<=n;i++){ scanf("%d",&a[i]); tot++; pos[tot]=a[i]; } for(i=1;i<=m;i++){ scanf("%s",str); if(str[0]=='Q'){ scanf("%d%d%d",&c,&d,&e); ques[i].kind=0;ques[i].l=c;ques[i].r=d;ques[i].d=e; } else if(str[0]=='C'){ scanf("%d%d",&c,&d); tot++;pos[tot]=d; ques[i].kind=1;ques[i].l=c;ques[i].r=d; } } sort(pos+1,pos+1+tot); tot=unique(pos+1,pos+1+tot)-pos-1; th=0; T[0]=build(1,tot); for(i=1;i<=n;i++){ int t=lower_bound(pos+1,pos+1+tot,a[i])-pos; T[i]=update(T[i-1],t,1); } for(i=1;i<=n;i++){ S[i]=T[0]; } for(i=1;i<=m;i++){ if(ques[i].kind==0){ //表示询问 printf("%d\n",pos[question(ques[i].l,ques[i].r,ques[i].d)]); } else{ int t1=lower_bound(pos+1,pos+1+tot,a[ques[i].l])-pos; int t2=lower_bound(pos+1,pos+1+tot,ques[i].r)-pos; modify(ques[i].l,t1,-1); modify(ques[i].l,t2,1); a[ques[i].l ]=ques[i].r; //!!! } } } return 0; } /* 2 5 3 3 2 1 4 7 Q 1 4 3 C 2 6 Q 2 5 3 5 3 3 2 1 4 7 Q 1 4 3 C 2 6 Q 2 5 3 */