Codeforces Round #220 (Div. 2) D:http://codeforces.com/contest/374/problem/D
题意:给你m个数,这m个数是递增的。然后给你n个操作,每个操作是一个数1,0,-1,如果是1或者0,就把这个数数直接放在序列的末位,刚开始的时候,序列为空。当操作数是-1的时候,只要把ai<=当期序列长度,就把ai所对应的那一位删除。
题解:用树状数组和二分搞。首先如果是0或者1,直接把这个数放进去,把这个数的位子加一。然后更新的时候,首先查询到小于等于序列长度的那些数,表示要删除在该序列的第几个数,然后用二分找到这个数,但是这里不能直接删除,要先保存,然后等所有的数都找完了,再进行统一删除。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=1e6+10; 7 int c[N],a[N],ans[N],top,as[N]; 8 int n,m,sum; 9 void init(){ 10 memset(c,0,sizeof(c)); 11 memset(a,0,sizeof(a)); 12 memset(ans,-1,sizeof(ans)); 13 top=0; 14 } 15 int lowbit(int x){ 16 return x&(-x); 17 18 } 19 void add(int x,int val){ 20 while(x<=m){ 21 c[x]+=val; 22 x+=lowbit(x); 23 } 24 } 25 26 int getsum(int x){ 27 int ans=0; 28 while(x){ 29 ans+=c[x]; 30 x-=lowbit(x); 31 } 32 return ans; 33 } 34 void work(int num,int ct){ 35 int l=1,r=m; 36 while(l<r){ 37 int mid=(l+r)/2; 38 //printf("%d ",mid); 39 if(getsum(mid)>=num)r=mid; 40 else 41 l=mid+1; 42 } 43 as[ct]=l; 44 } 45 int t; 46 int main(){ 47 while(~scanf("%d%d",&m,&n)){ 48 init(); 49 for(int i=1;i<=n;i++){ 50 scanf("%d",&a[i]); 51 } 52 for(int i=1;i<=m;i++){ 53 scanf("%d",&t); 54 if(t==0||t==1){ 55 ans[++top]=t; 56 sum++; 57 add(top,1); 58 } 59 else{ 60 int temp=lower_bound(a+1,a+n+1,sum)-a; 61 if(temp>n)temp--; 62 else if(a[temp]>sum)temp--; 63 sum-=temp; 64 // printf("%d ",temp); 65 for(int i=1;i<=temp;i++) 66 work(a[i],i); 67 for(int i=1;i<=temp;i++){ 68 add(as[i],-1); 69 ans[as[i]]=-1; 70 } 71 } 72 73 } 74 bool flag=false; 75 for(int i=1;i<=m;i++){ 76 if(ans[i]==-1)continue; 77 printf("%d",ans[i]); 78 flag=true; 79 } 80 if(!flag)printf("Poor stack!"); 81 puts(""); 82 83 } 84 }