题目链接:http://poj.org/problem?id=2761
题意:给定一个序列,有N个数,给定M个询问,询问的形式为 a b c ,询问区间[a,b]内第c小的数。
解题方法:一次性读入所有的询问,然后把询问进行排序,排序的顺序为终点小的在前,终点一样,起点大的在前,然后对排序后的每个询问进行处理,每次保证SBT中只有区间[a,b]的数(用插入和删除操作来保证),然后查询第K小。
总结:注意旋转操作调整size域的顺序。 不能搞反。
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; struct KEY { int wgt,num; KEY(int w=0,int n=0):wgt(w),num(n){} bool operator < (const KEY &k) const { if(wgt!=k.wgt)return wgt<k.wgt; return num<k.num; } bool operator == (const KEY &k) const { return wgt==k.wgt&&num==k.num; } }; const int MAXN = 100010; struct SBT { int l[MAXN],r[MAXN],pool[MAXN],size[MAXN],TOP,NODE,ROOT; KEY Key[MAXN]; void init() { TOP = NODE = ROOT = 0; size[0] = l[0] = r[0] = 0; } int newnode(KEY k) { int node; if(TOP)node = pool[TOP--]; else node = ++NODE; Key[node] = k; size[node] = 1; l[node] = r[node] = 0; return node; } void delnode(int x) { pool[++TOP] = x; Key[x].wgt = Key[x].num = size[x] = l[x] = r[x] = 0; } void left_rotate(int &p) { int x = r[p]; r[p] = l[x]; l[x] = p; size[x] = size[p]; size[p] = size[l[p]]+size[r[p]]+1; p = x; } void right_rotate(int &p) { int x = l[p]; l[p] = r[x]; r[x] = p; size[x] = size[p]; size[p] = size[l[p]]+size[r[p]]+1; p = x; } void Maintain(int &p,bool flag) { if(flag==0) { if(size[l[l[p]]]>size[r[p]])right_rotate(p); else if(size[r[l[p]]]>size[r[p]]) { left_rotate(l[p]); right_rotate(p); } else return; } else { if(size[r[r[p]]]>size[l[p]])left_rotate(p); else if(size[l[r[p]]]>size[l[p]]) { right_rotate(r[p]); left_rotate(p); } else return; } Maintain(l[p],0); Maintain(r[p],1); Maintain(p,1); Maintain(p,0); } void insert(int &p,KEY k) { if(!p) { p = newnode(k); return; } if(k<Key[p])insert(l[p],k); else insert(r[p],k); size[p] = size[l[p]]+size[r[p]]+1; Maintain(p,!(k<Key[p])); } int findmin(int p) { if(l[p])return findmin(l[p]); else return p; } void remove(int &p,KEY k) { if(p) { if(k==Key[p]) { if(!l[p]) { int x = p; p = r[p]; delnode(x); } else if(!r[p]) { int x = p; p = l[p]; delnode(x); } else { int x = findmin(r[p]); Key[p] = Key[x]; remove(r[p],Key[x]); } } else if(k<Key[p])remove(l[p],k); else remove(r[p],k); if(p) { size[p] = size[l[p]]+size[r[p]]+1; } } } int Select(int p,int k) { int rank = size[l[p]]+1; if(k==rank)return p; else if(k<rank)return Select(l[p],k); return Select(r[p],k-rank); } void print(int p) { if(!p)return ; print(l[p]); cout<<size[p]<<" "<<Key[p].wgt<<" "<<l[p]<<" "<<r[p]<<" "<<p<<" "<<(size[l[p]]+size[r[p]]+1)<<endl; print(r[p]); } }sbt; int arr[MAXN],res[50010]; struct Range { int a,b,c,num; bool operator < (const Range &r) const { if(b!=r.b)return b<r.b; else return a>r.a; } }R[50010]; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { int a,b;sbt.init(); for(int i=1;i<=n;i++) { scanf("%d",&arr[i]); } for(int i=1;i<=m;i++) { scanf("%d%d%d",&R[i].a,&R[i].b,&R[i].c); R[i].num = i; } sort(R+1,R+m+1);a = R[1].a; b = R[1].b; for(int i=a;i<=b;i++) { sbt.insert(sbt.ROOT,KEY(arr[i],i)); } res[R[1].num] = sbt.Key[sbt.Select(sbt.ROOT,R[1].c)].wgt; for(int i=2;i<=m;i++) { if(R[i].a<a) { for(int j=R[i].a;j<a;j++) { sbt.insert(sbt.ROOT,KEY(arr[j],j)); } for(int j=b+1;j<=R[i].b;j++) { sbt.insert(sbt.ROOT,KEY(arr[j],j)); } } else if(R[i].a<b) { for(int j=a;j<R[i].a;j++){ sbt.remove(sbt.ROOT,KEY(arr[j],j)); } for(int j=b+1;j<=R[i].b;j++){ sbt.insert(sbt.ROOT,KEY(arr[j],j)); } } else { for(int j=a;j<=b;j++){ sbt.remove(sbt.ROOT,KEY(arr[j],j)); } for(int j=R[i].a;j<=R[i].b;j++){ sbt.insert(sbt.ROOT,KEY(arr[j],j)); } } a = R[i].a, b = R[i].b; res[R[i].num] = sbt.Key[sbt.Select(sbt.ROOT,R[i].c)].wgt; } for(int i=1;i<=m;i++)printf("%d\n",res[i]); } return 0; }