科大讯飞杯 H-时空栈 线段树

题目链接: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;
}
原创文章 85 获赞 103 访问量 2473

猜你喜欢

转载自blog.csdn.net/weixin_43824564/article/details/106134939
今日推荐