活躍區的操作序列的優先順序單調不上升,所以每次undo的一定是一段區間。
以優先順序為權值建立可持久化權值線段樹,維護優先順序在某區間內的最靠後的位置。
#include<cstdio> const int N=300010,M=6000000; int n,i,j,x,f[N],root[N],v[M],l[M],r[M],tot; inline void read(int&a){ char c;bool f=0;a=0; while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-'))); if(c!='-')a=c-'0';else f=1; while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0'; if(f)a=-a; } inline int max(int a,int b){return a>b?a:b;} int ins(int x,int a,int b,int c,int d){ int y=++tot;v[y]=max(v[x],d); if(a==b)return y; int mid=(a+b)>>1; if(c<=mid)l[y]=ins(l[x],a,mid,c,d),r[y]=r[x];else l[y]=l[x],r[y]=ins(r[x],mid+1,b,c,d); return y; } int ask(int x,int a,int b,int c){ if(!x)return 0; if(b<=c)return v[x]; int mid=(a+b)>>1,t=ask(l[x],a,mid,c); if(c>mid)t=max(t,ask(r[x],mid+1,b,c)); return t; } int main(){ for(read(n),i=1;i<=n;printf("%d\n",f[i++])){ read(x); if(x>0)f[i]=x,root[i]=ins(root[i-1],0,n,0,i); else f[i]=f[j=ask(root[i-1],0,n,-x-1)-1],root[i]=ins(root[j],0,n,-x,i); } return 0; }