Time Limit: 6000MS | Memory Limit: 65536KB | 64bit IO Format: %lld & %llu |
Description
Your task is to help Jiajia calculate which dog ate the food after each feeding.
Input
The second line contains n integers, describe the pretty value of each dog from left to right. You should notice that the dog with lower pretty value is prettier.
Each of following m lines contain three integer i,j,k, it means that Jiajia feed the k-th pretty dog in this feeding.
You can assume that n<100001 and m<50001.
Output
Sample Input
7 2
1 5 2 6 3 7 4
1 5 3
2 7 1
Sample Output
3
2
Source
区间求第k大值。
treap树维护第k大值。
用类似莫队的方法,将区间排序,每次添加新进区间的数,删去已经出区间的数,然后在树上找第k大数。
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<cstdlib> 8 #include<ctime> 9 using namespace std; 10 const int mxn=100100; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 struct qry{ 18 int l,r; 19 int rk,id; 20 }a[mxn]; 21 int ans[mxn]; 22 int cmp(const qry q,const qry e){ 23 if(q.l!=e.l)return q.l<e.l; 24 return q.r<e.r; 25 } 26 struct node{ 27 int l,r; 28 int v,ct; 29 int size,rand; 30 }t[mxn]; 31 int root=0,cnt=0; 32 void update(int rt){ 33 t[rt].size=t[t[rt].l].size+t[t[rt].r].size+t[rt].ct; 34 return; 35 } 36 void ltt(int &rt){ 37 int now=t[rt].r; 38 t[rt].r=t[now].l; 39 t[now].l=rt; 40 t[now].size=t[rt].size; 41 update(rt); 42 rt=now; 43 return; 44 } 45 void rtt(int &rt){ 46 int now=t[rt].l; 47 t[rt].l=t[now].r; 48 t[now].r=rt; 49 t[now].size=t[rt].size; 50 update(rt); 51 rt=now; 52 return; 53 } 54 void insert(int &rt,int x){//新节点 插入值 55 if(!rt){ 56 t[++cnt].v=x; 57 t[cnt].size=1;t[cnt].rand=rand(); 58 t[cnt].ct=1; 59 rt=cnt; 60 return; 61 } 62 t[rt].size++; 63 if(t[rt].v==x)t[rt].ct++; 64 else if(x>t[rt].v){ 65 insert(t[rt].r,x); 66 if(t[t[rt].r].rand<t[rt].rand)ltt(rt); 67 } 68 else{ 69 insert(t[rt].l,x); 70 if(t[t[rt].l].rand<t[rt].rand)rtt(rt); 71 } 72 return; 73 } 74 void del(int &rt,int x){ 75 if(!rt)return; 76 if(t[rt].v==x){ 77 if(t[rt].ct>1){t[rt].size--;t[rt].ct--;return;} 78 if(t[rt].l*t[rt].r==0)rt=t[rt].l+t[rt].r;//子树补位 79 else{ 80 if(t[t[rt].l].rand<t[t[rt].r].rand){//把结点转到叶子上删除 81 rtt(rt); 82 del(rt,x); 83 } 84 else{ 85 ltt(rt); 86 del(rt,x); 87 } 88 } 89 return; 90 } 91 t[rt].size--; 92 if(x>t[rt].v)del(t[rt].r,x); 93 if(x<t[rt].v)del(t[rt].l,x); 94 return; 95 } 96 int query(int rt,int rank){ 97 if(!rt)return 0; 98 if(rank<=t[t[rt].l].size) return query(t[rt].l,rank); 99 if(rank>t[t[rt].l].size+t[rt].ct)return query(t[rt].r,rank-t[t[rt].l].size-t[rt].ct); 100 return t[rt].v; 101 } 102 // 103 int n,m; 104 int pt[mxn]; 105 106 int main(){ 107 t[0].size=0; 108 a[0].l=1;a[0].r=0; 109 srand(time(0)); 110 n=read();m=read(); 111 int i,j; 112 for(i=1;i<=n;i++)pt[i]=read(); 113 for(i=1;i<=m;i++){a[i].l=read();a[i].r=read();a[i].rk=read();a[i].id=i;} 114 sort(a+1,a+m+1,cmp); 115 for(i=1;i<=m;i++){ 116 if(a[i].l>a[i-1].r){ 117 root=0; 118 for(j=a[i].l;j<=a[i].r;j++)insert(root,pt[j]); 119 } 120 else{ 121 for(j=a[i-1].l;j<a[i].l;j++) del(root,pt[j]); 122 for(j=a[i-1].r+1;j<=a[i].r;j++) insert(root,pt[j]); 123 } 124 ans[a[i].id]=query(root,a[i].rk); 125 } 126 for(i=1;i<=m;i++)printf("%d\n",ans[i]); 127 return 0; 128 }