问题 B: 绝地求生
时间限制: 1 Sec 内存限制: 128 MB
提交: 61 解决: 20
[提交] [状态] [命题人:admin]
题目描述
吃鸡开局了,你降落的森林中有一条长度为S的小路(编号从1到S),且在小路上时常会起雾,你手上的激光发射器可以让雾消散。
你肯定你所在位置的视野。若位置x有浓雾,则位置x的视野为0。若从x一直到S或从x一直到1全都没有浓雾,则视野为INF。其他情况下,位置x的视野定义为max{R-L-1},其中L,R满足:,x0格子没有浓雾。
具体来说,会有以下事件发生:
1、“1 L R”小路的[L,R]部分产生了浓雾;
2、“2 L R”小路的[L,R]部分浓雾散去了;
3、“3 X”查询X点的视野。
一开始,小路上没有任何浓雾。
输入
第一行一个整数,为小路的长度S。
第二行一个整数,为事件数Q。
接下来Q行,每行一个事件,格式如题目描述。
输出
对于每一个询问事件,输出一个整数或一行字符串“INF”,代表所求视野。
样例输入
5 5 1 2 4 3 1 3 4 2 3 3 3 3
样例输出
INF 0 1
提示
对于 40%的数据,S*Q <= 5*10^7。
对于 100%的数据,2≤S≤100,000,2≤Q≤200,000,1≤L≤R≤S,1≤X≤S。
很显然,数据是随机出的,并没有卡我珂朵莉
/*author:revolIA*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5+7,mod = 1e9+7;
struct node{
int l,r;
mutable ll val;
bool operator < (const node o)const{
return l<o.l;
}
};
int n,q,ans,opt,l,r,x,y;
set<node> Tree;
typedef set<node>::iterator It;
It split(int pos){
It it = Tree.lower_bound({pos,pos,0});
if(it != Tree.end() && it->l == pos)return it;
--it;
int L = it->l,R = it->r;
ll val = it->val;
Tree.erase(it),Tree.insert({L,pos-1,val});
return Tree.insert({pos,R,val}).first;
}
void Assign(int l,int r,int val){
It itr = split(r+1),itl = split(l);
Tree.erase(itl,itr),Tree.insert({l,r,1LL*val});
}
void query(int x){
It pos = split(x);
if(pos->val == 1){
printf("0\n");
return;
}
int l = 1,r = n;
for(It i = pos;;i--){
if(i->val == 1){
l = i->r+1;
break;
}
if(i == Tree.begin())break;
}
for(It i = pos;i!=Tree.end();i++){
if(i->val == 1){
r = i->l-1;
break;
}
}
if(l==1 || r == n){
printf("INF\n");
}else{
printf("%d\n",r-l+1);
}
}
int main(){
scanf("%d%d",&n,&q);
Tree.insert({1,n,0});
while(q--){
scanf("%d",&opt);
if(opt == 1){
scanf("%d%d",&l,&r);
Assign(l,r,1);
}else if(opt == 2){
scanf("%d%d",&l,&r);
Assign(l,r,0);
}else{
scanf("%d",&l);
query(l);
}
}
return 0;
}