http://codeforces.com/problemset/problem/374/D
预处理每个-1操作要删哪几个数并存下来 这些操作数肯定是<=n的 然后线段树维护整个序列 然后扫一遍所有-1操作 每次二分查找来删掉对应位置的数即可
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const int maxm=1e6+10;
struct node
{
int val,gou;
};
node tree[4*maxn];
int pos[maxm],ary[maxn],pre[maxn];
int n,m;
void pushup(int cur)
{
tree[cur].val=tree[2*cur].val+tree[2*cur+1].val;
}
void build(int l,int r,int cur)
{
int m;
if(l==r){
if(ary[l]==-1) tree[cur].val=0,tree[cur].gou=-1;
else tree[cur].val=1,tree[cur].gou=ary[l];
return;
}
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
pushup(cur);
}
void update(int tar,int val,int l,int r,int cur)
{
int m;
if(l==r){
if(val==-1) tree[cur].val=0,tree[cur].gou=-1;
else tree[cur].val=1,tree[cur].gou=val;
return;
}
m=(l+r)/2;
if(tar<=tree[2*cur].val) update(tar,val,l,m,2*cur);
else update(tar-tree[2*cur].val,val,m+1,r,2*cur+1);
pushup(cur);
}
void safari(int l,int r,int cur)
{
int m;
if(l==r){
if(tree[cur].val) printf("%d",tree[cur].gou);
return;
}
m=(l+r)/2;
safari(l,m,2*cur);
safari(m+1,r,2*cur+1);
}
int main()
{
int i,j,cnt,p;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++) scanf("%d",&pos[i]);
for(i=1;i<=n;i++) scanf("%d",&ary[i]);
cnt=0;
for(i=1;i<=n;i++){
if(ary[i]==-1){
p=upper_bound(pos+1,pos+m+1,cnt)-pos-1;
pre[i]=p,cnt-=p;
}
else cnt++;
}
/*
for(i=1;i<=n;i++){
if(ary[i]==-1) printf("%d ",pre[i]);
}
printf("\n");
*/
if(cnt!=0)
{
build(1,n,1);
for(i=1;i<=n;i++){
if(ary[i]==-1){
for(j=1;j<=pre[i];j++){
update(pos[j]-j+1,-1,1,n,1);
}
}
}
safari(1,n,1);
}
else printf("Poor stack!\n");
return 0;
}