SHOI2015 脑洞治疗仪

给你一个序列,一开始都是 $1$,资瓷 $3$ 种操作

1.把 $[l,r]$ 赋值为 $0$

2.把 $[l,r]$ 中所有 $1$ 删掉,记录删掉的 $1$ 的个数,并把这些 $1$ 从左到右填到 $[a,b]$ 中的 $0$ 处,不考虑 $1$ 的剩余(剩下的相当于全扔了)

3.查询 $[l,r]$ 中最长连续的 $0$ 的个数

sol:

好像会珂朵莉树这题就是模拟啊...应该是当年 SHOI 的人不知道有这种黑珂技

感觉跑的比线段树快呀。。。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
    for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
    return x * f;
}
struct node
{
    int l,r;
    mutable bool v;
    node(int L,int R = -1,bool vv = 0):l(L),r(R),v(vv){}
    bool operator < (const node &b)const{return l < b.l;}
};
set<node> s;
int n,m;
inline set<node>::iterator split(int pos)
{
    auto it = s.lower_bound(node(pos));
    if(it != s.end() && it -> l == pos)return it;
    --it;int L = it -> l,R = it -> r,vv = it -> v;
    s.erase(it);s.insert(node(L,pos - 1,vv));
    return s.insert(node(pos,R,vv)).first;
}
inline void Rua(int l,int r,int v)
{
    auto itr = split(r + 1),itl = split(l);
    s.erase(itl,itr);
    s.insert(node(l,r,v));
}
inline void heal(int l,int r,int a,int b)
{
    auto itr = split(r + 1),itl = split(l),nowit = itl;
    int sum = 0;
    for(;itl != itr;++itl)
        if(itl -> v)
            sum += (itl -> r - itl -> l + 1);
    s.erase(nowit,itr);
    s.insert(node(l,r,0));
    if(!sum)return;
    itr = split(b + 1),itl = split(a),nowit = itl;
    if(sum >= b - a + 1)
    {
        s.erase(nowit,itr);
        s.insert(node(a,b,1));
        return;
    }
    for(;itl != itr;++itl)
        if(!itl -> v)
        {
            sum -= (itl -> r - itl -> l + 1);
            if(sum < 0)
            {
                Rua(itl -> l,itl -> r + sum,1);
                return;
            }
            else itl -> v = 1;
        }
}
inline int query(int l,int r)
{
    auto itr = split(r + 1),itl = split(l),nowit = itl;
    int mx = 0,now = 0;
    for(;itl != itr;++itl)
        if(!itl -> v)
            now += (itl -> r - itl -> l + 1);
        else if(now != 0)mx = max(mx,now),now = 0;
    return max(mx,now);
}
int main()
{
    n = read(),m = read();s.insert(node(1,n,1));
    while(m--)
    {
        int opt = read(),l = read(),r = read();
        if(!opt)Rua(l,r,0);
        else if(opt == 1)
        {
            int a = read(),b = read();
            heal(l,r,a,b);
        }
        else
        {
            printf("%d\n",query(l,r));
        }
    }
}
View Code

 

转载于:https://www.cnblogs.com/Kong-Ruo/p/9887298.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值