黑匣子_NOI导刊2010提高(06)
题目描述
Black Box是一种原始的数据库。它可以储存一个整数数组,还有一个特别的变量i。最开始的时候Black Box是空的.而i等于0。这个Black Box要处理一串命令。
命令只有两种:
ADD(x):把x元素放进BlackBox;
GET:i加1,然后输出Blackhox中第i小的数。
记住:第i小的数,就是Black Box里的数的按从小到大的顺序排序后的第i个元素。例如:
我们来演示一下一个有11个命令的命令串。(如下图所示)
现在要求找出对于给定的命令串的最好的处理方法。ADD和GET命令分别最多200000个。现在用两个整数数组来表示命令串:
1.A(1),A(2),…A(M):一串将要被放进Black Box的元素。每个数都是绝对值不超过2000000000的整数,M$200000。例如上面的例子就是A=(3,1,一4,2,8,-1000,2)。
2.u(1),u(2),…u(N):表示第u(j)个元素被放进了Black Box里后就出现一个GET命令。例如上面的例子中u=(l,2,6,6)。输入数据不用判错。
输入输出格式
输入格式:
第一行,两个整数,M,N。
第二行,M个整数,表示A(l)
……A(M)。
第三行,N个整数,表示u(l)
…u(N)。
输出格式:
输出Black Box根据命令串所得出的输出串,一个数字一行。
输入输出样例
说明
对于30%的数据,M≤10000;
对于50%的数据,M≤100000:
对于100%的数据,M≤200000。
不就是个可持久化线段树模板吗?
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=210000; 4 int n,m,cnt; 5 struct node 6 { 7 int l; 8 int r; 9 int sum; 10 } t[maxn*60]; 11 int rk[maxn],rt[maxn]; 12 struct p 13 { 14 int x; 15 int pp; 16 bool operator < (const p &_) const 17 { 18 return x<_.x; 19 } 20 } a[maxn]; 21 22 inline void bt(int &num,int &x,int l,int r) 23 { 24 t[cnt++]=t[x]; 25 x=cnt-1; 26 ++t[x].sum; 27 if(l==r) 28 return ; 29 int mid=(l+r)>>1; 30 if(num<=mid) 31 bt(num,t[x].l,l,mid); 32 else 33 bt(num,t[x].r,mid+1,r); 34 35 } 36 37 inline int query(int i,int j,int k,int l,int r) 38 { 39 if(l==r) 40 return l; 41 int tt=t[t[j].l].sum-t[t[i].l].sum; 42 int mid=(l+r)>>1; 43 if(k<=tt) 44 return query(t[i].l,t[j].l,k,l,mid); 45 else 46 return query(t[i].r,t[j].r,k-tt,mid+1,r); 47 } 48 49 int main() 50 { 51 t[0].l=t[0].r=t[0].sum; 52 rt[0]=0; 53 scanf("%d%d",&m,&n); 54 for(int i=1; i<=m; i++) 55 { 56 scanf("%d",&a[i].x); 57 a[i].pp=i; 58 } 59 sort(a+1,a+1+m); 60 for(int i=1; i<=m; i++) 61 rk[a[i].pp]=i; 62 cnt=1; 63 for(int i=1; i<=m; i++) 64 { 65 rt[i]=rt[i-1]; 66 bt(rk[i],rt[i],1,m); 67 } 68 for(int i=1;i<=n;i++) 69 { 70 int term; 71 scanf("%d",&term); 72 printf("%d\n",a[query(rt[0],rt[term],i,1,m)].x); 73 } 74 return 0; 75 }