题意:
给定一系列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;
}