题目链接:https://ac.nowcoder.com/acm/contest/5477/H
题目有个要点就是 每个时间点t都只会出现一次 这样对于0操作 我们可以把它入栈的值放在这个时间点 对于入栈操作 我们把对应的时间点+1,对于出栈操作 我们把对应的时间点-1 然后我们来研究一下对于每次询问我们要找哪个点 (需要离散化时间点)
区间 1 2 3 4 5 6 7
值 - - - - - - -
标记 0 0 0 0 0 0 0
后缀和 0 0 0 0 0 0 0
一开始是这样的初始状态
试着尝试 如下操作
0 1 2
2 2
0 2 1
2 3
1 3
2 4
第一次操作后:
区间 1 2 3 4 5 6 7
值 2 - - - - - -
标记 1 0 0 0 0 0 0
后缀和 1 0 0 0 0 0 0
第一次询问 2 2 我们询问到的显然是位于1时间点的值2
第二次操作后:
区间 1 2 3 4 5 6 7
值 2 1 - - - - -
标记 1 1 0 0 0 0 0
后缀和 2 1 0 0 0 0 0
第二次询问 2 3 我们询问到的是位于2时间点的值1
第三次操作后:
区间 1 2 3 4 5 6 7
值 2 1 - - - - -
标记 1 1 -1 0 0 0 0
后缀和 1 0 -1 0 0 0 0
第三次询问我们得到的是位于1时间点的值2
显然 每次询问我们都要找到后缀和为1的最靠右边的时间点 我们用线段树来维护即可
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
struct node{
int sum,mx; //sum是区间和 mx是区间最大后缀
node(){sum=0,mx=0;}
void setx(int v){sum=mx=v;}
}tr[N<<2];
struct Query{
int op,t,v;
}q[N];
node cal(node a,node b){
node c;
c.sum = a.sum + b.sum;
c.mx = max(b.sum+a.mx,b.mx);
return c;
}
int n,tot,res,b[N],val[N];
void update(int id,int l,int r,int pos,int fla){
if(l==r){
if(!fla) tr[id].setx(1);
else tr[id].setx(-1);
return;
}
int mid = l+r>>1;
if(pos<=mid) update(lson,pos,fla);
else update(rson,pos,fla);
tr[id]=cal(tr[id<<1],tr[id<<1|1]);
}
void Q1(node x,int id,int l,int r){//寻找区间l~r的后缀和为1的最右端点
if(l==r){
res=val[l];
return;
}
int mid = l+r>>1;
if(cal(tr[id<<1|1],x).mx>0) Q1(x,rson);
else Q1(cal(tr[id<<1|1],x),lson);
}
void Q2(int id,int l,int r,node &x,int pos){//寻找合法的右端点
if(l==r){
if(tr[id].mx>0)
Q1(x,id,l,r);
return;
}
int mid = l+r>>1;
if(pos<=mid) Q2(lson,x,pos);
else{
Q2(rson,x,pos);
if(!res){//在回溯的过程中进行Q1询问
if(cal(tr[id<<1],x).mx>0)
Q1(x,lson);
x=cal(tr[id<<1],x);
}
}
}
int main(){
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d",&q[i].op);
if(q[i].op) scanf("%d",&q[i].t);
else scanf("%d%d",&q[i].t,&q[i].v);
b[i]=q[i].t;
}
sort(b+1,b+1+n);
tot=unique(b+1,b+1+n)-b-1;//b数组是离散化
for(int i = 1; i <= n; i++){
q[i].t=lower_bound(b+1,b+1+tot,q[i].t)-b;
if(q[i].op==0) val[q[i].t]=q[i].v;
if(q[i].op==2){
res=0;
node x;
Q2(1,1,tot,x,q[i].t);
printf("%d\n",res);
}else update(1,1,tot,q[i].t,q[i].op);
}
return 0;
}