线段数维护区间有几个没有被删除的数,利用线段树的二分找第几个数在哪里,然后模拟更新就好啦。
#include<bits/stdc++.h> #define fi first #define se second #define mk make_pair #define pii make_pair #define ll long long #define read(x) scanf("%d",&x) #define sread(x) scanf("%s",x) #define dread(x) scanf("%lf",&x) #define lread(x) scanf("%lld",&x) using namespace std; const int inf=0x3f3f3f3f; const int N=2e6+7; int n,m,a[N],dfn; struct seg_tree { struct node { int l,r,sum,v; }a[N<<2]; void Build(int l,int r,int rt) { a[rt].l=l; a[rt].r=r; a[rt].sum=a[rt].v=0; if(l==r) return; int mid=(l+r)>>1; Build(l,mid,rt<<1); Build(mid+1,r,rt<<1|1); } void Modify(int pos,int rt,int v) { int l=a[rt].l,r=a[rt].r; if(l==r && l==pos) { a[rt].v=v; a[rt].sum=1; return; } int mid=(l+r)>>1; if(pos<=mid) Modify(pos,rt<<1,v); else Modify(pos,rt<<1|1,v); a[rt].sum=a[rt<<1].sum+a[rt<<1|1].sum; } void Delete(int pos,int rt) { int l=a[rt].l, r=a[rt].r; if(l==r) { a[rt].sum=0; a[rt].v=0; return; } if(pos<=a[rt<<1].sum) Delete(pos,rt<<1); else Delete(pos-a[rt<<1].sum,rt<<1|1); a[rt].sum=a[rt<<1].sum+a[rt<<1|1].sum; } void Print(int rt) { int l=a[rt].l,r=a[rt].r; if(l==r) { printf("%d",a[rt].v); return; } if(a[rt<<1].sum) Print(rt<<1); if(a[rt<<1|1].sum) Print(rt<<1|1); } }seg; int main() { read(n),read(m); for(int i=0;i<m;i++) read(a[i]); seg.Build(1,n+1,1); while(n--) { int op; read(op); if(op==-1) { for(int i=0;i<m;i++) { if(seg.a[1].sum<a[i]-i) break; seg.Delete(a[i]-i,1); } } else seg.Modify(++dfn,1,op); } if(!seg.a[1].sum) puts("Poor stack!"); else seg.Print(1); return 0; }