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));
        }
    }
}

原文地址:https://www.cnblogs.com/Kong-Ruo/p/9887298.html

时间: 2024-10-15 19:55:21

SHOI2015 脑洞治疗仪的相关文章

bzoj4592 [Shoi2015]脑洞治疗仪

Description 曾经发明了自动刷题机的发明家SHTSC又公开了他的新发明:脑洞治疗仪--一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个01序列.1代表这个位置的脑组织正常工作,0代表这是一块脑洞. 1 0 1 0 0 0 1 1 1 0 脑洞治疗仪修补某一块脑洞的基本工作原理就是将另一块连续区域挖出,将其中正常工作的脑组织填补在这块脑洞中. (所以脑洞治疗仪是脑洞的治疗仪?) 例如,用上面第8号位置到第10号位置去修补第1号位置到第4号位置的脑洞.我

[SHOI2015]脑洞治疗仪(线段树?珂朵莉树)

题面 这道题超级可爱呢,珂朵莉最可爱了,不,小哀才是最可爱的呢 很好的题,可以考虑用线段树维护,hale表示线段树思路很难,而且难打,不如滚去写珂朵莉树哦 对于操作一:直接将set修改插入即可 对于操作三:最大连续子段和(线段树里面是这样叫的吧)维护即可 对于操作二:我们发现可以考虑先将这段区间里面的1 全部取出来,然后暴力合并区间为0,插入会set里面 之后枚举要修改的区间,从左端点开始搞起,一直后搜索,最后加一个判断,是否已经完全ok即可,具体可参见代码 好了,这道题就解决了 我的代码好像l

【BZOJ-4592】脑洞治疗仪 线段树

4592: [Shoi2015]脑洞治疗仪 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 69  Solved: 38[Submit][Status][Discuss] Description 曾经发明了自动刷题机的发明家SHTSC又公开了他的新发明:脑洞治疗仪--一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个01序列.1代表这个位置的脑组织正常工作,0代表这是一块脑洞. 1 0 1 0 0 0 1 1 1

LOJ #2037. 「SHOI2015」脑洞治疗仪

#2037. 「SHOI2015」脑洞治疗仪 题目描述 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个 01 序列.1 代表这个位置的脑组织正常工作,0 代表这是一块脑洞. 1 0 1 0 0 0 1 1 1 0 脑洞治疗仪修补某一块脑洞的基本工作原理就是将另一块连续区域挖出,将其中正常工作的脑组织填补在这块脑洞中.(所以脑洞治疗仪是脑洞的治疗仪?) 例如,用上面第 8 号位置到第 

LibreOJ #2037. 「SHOI2015」脑洞治疗仪

线段树区间合并问题 恶心... 屠龙宝刀点击就送 #include <cstdio> #define N 200005 struct Segment { int l,r,mid,sum,lm,rm,m,len,flag; Segment * ch[2]; Segment () { ch[0]=ch[1]=NULL; lm=rm=m=0; flag=-1; } }*root=new Segment; int n,m,tmp,ans,nowl; inline int max(int a,int b

BZOJ 4592 脑洞治疗仪

天啦噜我自己YY的从任意起点开始的线段树上二分居然是对的.... 好感动啊. 4.7k的代码只调了一个晚上好感动. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 200500 using namespace std; int n,m,sum[maxn<<2],lazy[maxn<<2],ls[maxn<

Bzoj 4591: [Shoi2015]超能粒子炮&#183;改 数论,Lucas定理,排列组合

4591: [Shoi2015]超能粒子炮·改 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 178  Solved: 70[Submit][Status][Discuss] Description 曾经发明了脑洞治疗仪&超能粒子炮的发明家SHTSC又公开了他的新发明:超能粒子炮·改--一种可以发射威力更加 强大的粒子流的神秘装置.超能粒子炮·改相比超能粒子炮,在威力上有了本质的提升.它有三个参数n,k.它会 向编号为0到k的位置发射威力为C(n

BZOj-4591: [Shoi2015]超能粒子炮&#183;改 (Lucas+排列组合)

4591: [Shoi2015]超能粒子炮·改 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 960  Solved: 360[Submit][Status][Discuss] Description 曾经发明了脑洞治疗仪&超能粒子炮的发明家SHTSC又公开了他的新发明:超能粒子炮·改--一种可以发射威力更加 强大的粒子流的神秘装置.超能粒子炮·改相比超能粒子炮,在威力上有了本质的提升.它有三个参数n,k.它会 向编号为0到k的位置发射威力为C(

【bzoj4591】 [Shoi2015]超能粒子炮&#183;改

Description 曾经发明了脑洞治疗仪&超能粒子炮的发明家SHTSC又公开了他的新发明:超能粒子炮·改--一种可以发射威力更加 强大的粒子流的神秘装置.超能粒子炮·改相比超能粒子炮,在威力上有了本质的提升.它有三个参数n,k.它会 向编号为0到k的位置发射威力为C(n,k) mod 2333的粒子流.现在SHTSC给出了他的超能粒子炮·改的参数,让你求 其发射的粒子流的威力之和模2333. Input 第一行一个整数t.表示数据组数. 之后t行,每行二个整数n,k.含义如题面描述. k<