「zoj2112」Dynamic Rankings
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
题解
线段树套平衡树,在线段树的每一个区间内套一棵平衡树
然后二分值判断区间内比它小的数的个数
似乎比可持久更好理解
主要是代码量比较大
treap写的不够顺手
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #define N 200001 #define M 1300001 using namespace std; int T,n,m,tmp; int a[50001],root[N]; int sz,s[M],ls[M],rs[M],v[M],w[M],rnd[M]; void update(int k) {s[k]=s[ls[k]]+s[rs[k]]+w[k];} void rturn(int &k) {int t=ls[k];ls[k]=rs[t];rs[t]=k;s[t]=s[k];update(k);k=t;} void lturn(int &k) {int t=rs[k];rs[k]=ls[t];ls[t]=k;s[t]=s[k];update(k);k=t;} void insert(int &k,int num) { if(!k) {k=++sz;s[k]=w[k]=1;ls[k]=rs[k]=0;rnd[k]=rand();v[k]=num;return;} s[k]++; if(v[k]==num)w[k]++; else if(num<v[k]) {insert(ls[k],num);if(rnd[ls[k]]<rnd[k])rturn(k);} else {insert(rs[k],num);if(rnd[rs[k]]<rnd[k])lturn(k);} } void del(int &k,int num) { if(v[k]==num) { if(w[k]>1){w[k]--;s[k]--;return;} if(ls[k]*rs[k]==0)k=ls[k]+rs[k]; else if(rnd[ls[k]]<rnd[rs[k]]) {rturn(k);del(k,num);} else {lturn(k);del(k,num);} } else if(num<v[k]){del(ls[k],num);s[k]--;} else {del(rs[k],num);s[k]--;} } void change(int k,int l,int r,int x,int num,int y) { del(root[k],y); insert(root[k],num); if(l==r)return; int mid=(l+r)>>1; if(x<=mid)change(k<<1,l,mid,x,num,y); else change(k<<1|1,mid+1,r,x,num,y); } void build(int k,int l,int r,int x,int num) { insert(root[k],num); if(l==r)return; int mid=(l+r)>>1; if(x<=mid)build(k<<1,l,mid,x,num); else build(k<<1|1,mid+1,r,x,num); } void find(int k,int num) { if(!k)return; if(v[k]<=num){tmp+=s[ls[k]]+w[k];find(rs[k],num);} else find(ls[k],num); } void que(int k,int l,int r,int x,int y,int num) { if(l==x&&r==y){find(root[k],num);return;} int mid=(l+r)>>1; if(mid>=y)que(k<<1,l,mid,x,y,num); else if(mid<x)que(k<<1|1,mid+1,r,x,y,num); else { que(k<<1,l,mid,x,mid,num); que(k<<1|1,mid+1,r,mid+1,y,num); } } int main() { scanf("%d",&T); while(T--) { memset(root,0,sizeof(root)); sz=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){scanf("%d",&a[i]);} for(int i=1;i<=n;i++)build(1,1,n,i,a[i]); for(int i=1;i<=m;i++) { char s[3];int x,y,z; scanf("%s",s); if(s[0]=='C') { scanf("%d%d",&x,&y); change(1,1,n,x,y,a[x]); a[x]=y; } else { scanf("%d%d%d",&x,&y,&z); int l=0,r=1000000000; while(l<=r) { int mid=(l+r)>>1; tmp=0;que(1,1,n,x,y,mid); if(tmp>=z)r=mid-1; else l=mid+1; } printf("%d\n",l); } } } return 0; } |
求问root数组在哪里修改过吗?我没看出来。如果没修改,那作用是什么?
insert和del的k是&k
系统:正在调用fc函数
系统:正在对比文件zoj2112from lwher && zoj2112from hzwer
系统:找不到相异处……
23333
大神。群里好多人拜摸你!求加群 : 318135341