绝地求生(珂朵莉树)

问题 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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值