题意:
给定一系列push,pop,peak操作。每各操作都有一个不同的时间戳。下面介绍操作;
push w t,将w加入栈,t为时间戳。
pop t,将最后一个元素取出,t为时间戳。
peak t,输出栈顶的元素,t为时间戳。若不存在,输出-1
现在进行一个操作,时间戳为t1,由三个步骤,
1)将所有时间戳大于t1的操作还原。
2)执行该操作。
3)重新执行被还原的操作。
题解:
先将时间戳从小到大排列后离散化,然后根据时间戳建线段树。线段树结点由两个元素,sum表示该段的所有元素和,rmax表示该段的最大后缀和。上述题意可以转换成push操作就是讲对应时间戳+1,pop将对应时间戳-1,peak t操作就是求最大的t‘使得,[t',t)的元素和大于0。
在查询的过程中,我们从查询的时间戳t开始,从右到左查询,每次不存在时用len记录已经查询过的区间和。每次判断下len+这段区间的最大后缀和是否大于0,是的话继续查询,不是的话更新len,直至查询到叶子节点。那么叶子节点就是我们要求的时间戳,其对应的w就是所求值了。
代码:
#include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <map> #include <set> #include <vector> #include <cctype> using namespace std; #define lc (c<<1) #define rc (c<<1|1) const int maxn=5e4+10; struct node{ int l,r,rmax,sum; }e[maxn*4]; struct op{ char ch[10]; int w,t; }f[maxn]; int val[maxn*4],discrete[maxn],tt,len; int get_id(int x) { return lower_bound(discrete,discrete+tt,x)-discrete; } void build(int a,int b,int c) { e[c].l=a;e[c].r=b; e[c].rmax=e[c].sum=0; if(a==b)return ; int mid=(a+b)>>1; build(a,mid,lc); build(mid+1,b,rc); } void update(int a,int b,int c,int d) { if(e[c].l==a&&e[c].r==b) { val[c]=d; if(d>=0) { e[c].sum=e[c].rmax=1; } else { e[c].sum=-1; e[c].rmax=0; } return ; } int mid=(e[c].l+e[c].r)>>1; if(b<=mid)update(a,b,lc,d); else if(a>mid)update(a,b,rc,d); e[c].sum=e[lc].sum+e[rc].sum; e[c].rmax=max(e[rc].rmax,e[rc].sum+e[lc].rmax); } int query(int a,int c) { if(e[c].r<=a) { int s=len+e[c].rmax; if(s<=0) { len+=e[c].sum; return -1; } } if(e[c].l==e[c].r)return val[c]; int mid=(e[c].l+e[c].r)>>1; if(mid<a) { int ans=query(a,rc); if(ans!=-1)return ans; } return query(a,lc); } void readchar(char *s) { int i=0; char ch=getchar(); while(!(ch<='z'&&ch>='a'))ch=getchar(); while(ch<='z'&&ch>='a') { s[i++]=ch; ch=getchar(); } s[i]='\0'; } int readint() { int x=0; char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar(); } return x; } int main() { //freopen("D:\\1008.in","r",stdin); //freopen("C:\\Documents and Settings\\Administrator\\桌面\\false.out","w",stdout); int n,tot=0; while(scanf("%d",&n)!=EOF) { if(n==0)break; int i,j,k; tt=0; for(i=0;i<n;i++) { //scanf("%s",f[i].ch); readchar(f[i].ch); if(f[i].ch[1]=='u') { //scanf("%d%d",&f[i].w,&f[i].t); f[i].w=readint(); f[i].t=readint(); } else //scanf("%d",&f[i].t); f[i].t=readint(); if(f[i].ch[1]!='e')discrete[tt++]=f[i].t; } sort(discrete,discrete+tt); build(0,tt-1,1); printf("Case #%d:\n",++tot); for(i=0;i<n;i++) { int id=get_id(f[i].t); if(f[i].ch[1]=='o')update(id,id,1,-1); else if(f[i].ch[1]=='u')update(id,id,1,f[i].w); else { if(id==0)printf("-1\n"); else { len=0; printf("%d\n",query(id-1,1)); } } } } return 0; }