探险

题目:

题目描述
小林和亮亮来到森林中探险, 森林中有一条长度为 S 的小路 (编号从 1 到 S) , 且在小路上时常会起雾,亮亮也可以用神光让雾消散。 小林则关心在某一位置的视野。若位置 x 有浓雾,则位置 x 的视野为 0。若 从 x 一直到 S 或从 x 一直到 1 全都没有浓雾,则视野为INF。其他情况下,位置x的视野为maxR−L+1maxR−L+1 要满足这个区间内没有浓雾的产生. 具体来说,会有以下事件发生: 1、“1 L R”小路的[L, R]部分产生了浓雾; 2、“2 L R”小路的[L, R]部分浓雾散去了。 3、“3 X” 查询 X 点的视野。 一开始,小路上没有任何浓雾。

输入输出格式
输入格式:
第一行一个整数,为小路的长度 S。 第二行一个整数,为事件数 Q。 接下来 Q 行,每行一个事件,格式如题目描述。

输出格式:
对于每一个询问事件,输出一个整数或一行字符串“INF”,代表所求视野。

输入输出样例
输入样例#15
5
1 2 4
3 1
3 4
2 3 3
3 3
输出样例#1: 
INF
0
1
说明
对于 40%的数据,SQ <= 510^7。

对于 100%的数据,2≤S≤100,000,2≤Q≤200,0001≤L≤R≤S,1≤X≤S。

思路:线段树。

代码:

#include<bits/stdc++.h>
using namespace std;

#define lson (o*2)
#define rson (o*2+1)
#define mid (l+r)/2

#define maxn 100000
#define read(x) scanf("%d",&x)

struct Node{
	int L,R;
	int x,lzy;
	int xl,xr;
	int lsz,rsz;
};

int n,m;

int P,Q;
Node a[maxn*10];

void push_up(int o) {
	if(a[lson].x>a[rson].x) {
		a[o].x=a[lson].x;
		a[o].xl=a[lson].xl,a[o].xr=a[lson].xr;
	} else {
		a[o].x=a[rson].x;
		a[o].xl=a[rson].xl,a[o].xr=a[rson].xr;
	}
	if(a[lson].rsz+a[rson].lsz>a[o].x) {
		a[o].x=a[lson].rsz+a[rson].lsz;
		a[o].xl=a[lson].R-a[lson].rsz+1,a[o].xr=a[rson].L+a[rson].lsz-1;
	}
	a[o].lsz=a[lson].lsz,a[o].rsz=a[rson].rsz;
	if(a[lson].lsz==a[lson].R-a[lson].L+1) a[o].lsz=a[lson].lsz+a[rson].lsz;
	if(a[rson].rsz==a[rson].R-a[rson].L+1) a[o].rsz=a[rson].rsz+a[lson].rsz;
}

void push_down(int o) {
	if(a[o].lzy==0) {
		a[lson].x=a[lson].lsz=a[lson].rsz=a[lson].R-a[lson].L+1;
		a[rson].x=a[rson].lsz=a[rson].rsz=a[rson].R-a[rson].L+1;
		a[lson].lzy=a[rson].lzy=0;
		a[lson].xl=a[lson].L,a[lson].xr=a[lson].R;
		a[rson].xl=a[rson].L,a[rson].xr=a[rson].R;
		a[o].lzy=-1;
	} else if(a[o].lzy==1) {
		a[lson].x=a[lson].lsz=a[lson].rsz=0;
		a[rson].x=a[rson].lsz=a[rson].rsz=0;
		a[lson].lzy=a[rson].lzy=1;
		a[lson].xl=a[lson].L,a[lson].xr=a[lson].R;
		a[rson].xl=a[rson].L,a[rson].xr=a[rson].R;
		a[o].lzy=-1;
	}
}

void build(int o,int l,int r) {
	a[o].L=a[o].xl=l,a[o].R=a[o].xr=r;
	a[o].lzy=-1;a[o].x=a[o].lsz=a[o].rsz=r-l+1;
	if(l==r) return ;
	build(lson,l,mid),build(rson,mid+1,r);
}

void update(int o,int l,int r,int d) {
	push_down(o);
	if(l>Q||r<P) return ;
	if(l>=P&&r<=Q) {
		a[o].lzy=d;
		if(d==0) a[o].x=a[o].lsz=a[o].rsz=a[o].R-a[o].L+1;
		else a[o].x=a[o].lsz=a[o].rsz=0;
		a[o].xl=l,a[o].xr=r;
		return ;
	}
	update(lson,l,mid,d),update(rson,mid+1,r,d);
	push_up(o);
}

int query(int o,int l,int r) {
	push_down(o);
	if(l>P||r<P) return 0;
	if(a[o].xl<=P&&a[o].xr>=P) return a[o].x;
	int x=max(query(lson,l,mid),query(rson,mid+1,r));
	int L=a[lson].R-a[lson].rsz+1,R=a[rson].L+a[rson].lsz-1;
	if(L<=P&&R>=P) x=max(x,R-L+1);
	return x;
}

int main() {
	read(n),read(m);
	build(1,1,n);
	while(m--) {
		int opr;
		read(opr);
		if(opr==1) {
			read(P),read(Q);
			update(1,1,n,1);
		} else if(opr==2) {
			read(P),read(Q);
			update(1,1,n,0);
		} else {
			read(P);int PP=P;
			int ans=query(1,1,n);
			int x1,xn;
			P=1,x1=query(1,1,n);
			P=n,xn=query(1,1,n);
			if(x1>=PP||PP+xn>n) printf("INF\n");
			else printf("%d\n",ans);
		}
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值