bzoj4592 [Shoi2015]脑洞治疗仪

Description

曾经发明了自动刷题机的发明家SHTSC又公开了他的新发明:脑洞治疗仪--一种可以治疗他因为发明而日益增大的脑洞的神秘装置。

为了简单起见,我们将大脑视作一个01序列。1代表这个位置的脑组织正常工作,0代表这是一块脑洞。

1 0 1 0 0 0 1 1 1 0

脑洞治疗仪修补某一块脑洞的基本工作原理就是将另一块连续区域挖出,将其中正常工作的脑组织填补在这块脑洞中。

(所以脑洞治疗仪是脑洞的治疗仪?)

例如,用上面第8号位置到第10号位置去修补第1号位置到第4号位置的脑洞。我们就会得到:

1 1 1 1 0 0 1 0 0 0

如果再用第1号位置到第4号位置去修补第8号位置到第10号位置:

0 0 0 0 0 0 1 1 1 1

这是因为脑洞治疗仪会把多余出来的脑组织直接扔掉。

如果再用第7号位置到第10号位置去填补第1号位置到第6号位置:

1 1 1 1 0 0 0 0 0 0

这是因为如果新脑洞挖出来的脑组织不够多,脑洞治疗仪仅会尽量填补位置比较靠前的脑洞。

假定初始时SHTSC并没有脑洞,给出一些挖脑洞和脑洞治疗的操作序列,你需要即时回答SHTSC的问题:

在大脑某个区间中最大的连续脑洞区域有多大。

Input

第一行两个整数n,m。表示SHTSC的大脑可分为从1到n编号的n个连续区域。有m个操作。

以下m行每行是下列三种格式之一。

0 l r :SHTSC挖了一个从l到r的脑洞。

1 l0 r0 l1 r2 :SHTSC进行了一次脑洞治疗,用从l0到r0的脑组织修补l1到r1的脑洞。

2 l r :SHTSC询问l到r这段区间最大的脑洞有多大。

n,m <=200000,1<=l<=r<=n

Output

对于每个询问,输出一行一个整数,表示询问区间内最大连续脑洞区域有多大。

线段树维护区间信息:

区间从左开始连续的0个数
区间从右开始连续的0个数

区间连续0的最大长度

区间0的个数

区间长度

区间被0/1覆盖的标记

支持操作:

区间覆盖0/1

查询区间1的个数

查询区间最长的连续0的长度

#include<cstdio>
inline int input(){
    int x=0,c=getchar();
    while(c>57||c<48)c=getchar();
    while(c>47&&c<58)x=x*10+c-48,c=getchar();
    return x;
}
const int N=420000;
int n,m,l,r;
int c0[N],sz[N],lc[N],rc[N],f1[N],f0[N],ls[N],rs[N],ms[N],p=1,ans=0,pv,ptr;
inline int max(int a,int b){return a>b?a:b;}
inline void maxs(int&a,int b){if(a<b)a=b;}
int build(int L,int R){
    int w=p++;
    if(L<R){
        int M=L+R>>1;
        lc[w]=build(L,M);
        rc[w]=build(M+1,R);
        sz[w]=sz[lc[w]]+sz[rc[w]];
    }else sz[w]=1;
    return w;
}
inline void tag1(int w){
    if(!w)return;
    f1[w]=1;f0[w]=0;
    c0[w]=ls[w]=rs[w]=ms[w]=0;
}
inline void tag0(int w){
    if(!w)return;
    f1[w]=0;f0[w]=1;
    c0[w]=ls[w]=rs[w]=ms[w]=sz[w];
}
inline void up(int w){
    int l=lc[w],r=rc[w];
    ms[w]=max(ms[l],ms[r]);
    maxs(ms[w],rs[l]+ls[r]);
    ls[w]=ls[l];
    rs[w]=rs[r];
    if(ls[l]==sz[l])maxs(ls[w],ls[l]+ls[r]);
    if(rs[r]==sz[r])maxs(rs[w],rs[l]+rs[r]);
    c0[w]=c0[l]+c0[r];
    sz[w]=sz[l]+sz[r];
}
inline void dwn(int w){
    if(f1[w]){
        f1[w]=0;
        tag1(lc[w]);tag1(rc[w]);
    }
    if(f0[w]){
        f0[w]=0;
        tag0(lc[w]);tag0(rc[w]);
    }
}
void set0(int w=1,int L=1,int R=n){
    if(l<=L&&R<=r){
        tag0(w);
        return;
    }
    dwn(w);
    int M=L+R>>1;
    if(l<=M)set0(lc[w],L,M);
    if(r>M)set0(rc[w],M+1,R);
    up(w);
}
void get1(int w=1,int L=1,int R=n){
    if(l<=L&&R<=r){
        ans+=sz[w]-c0[w];
        return;
    }
    dwn(w);
    int M=L+R>>1;
    if(l<=M)get1(lc[w],L,M);
    if(r>M)get1(rc[w],M+1,R);
}
void set1(int w=1,int L=1,int R=n){
    if(!ans)return;
    if(l<=L&&R<=r&&c0[w]<=ans){
        ans-=c0[w];
        tag1(w);
        return;
    }
    dwn(w);
    int M=L+R>>1;
    if(l<=M)set1(lc[w],L,M);
    if(r>M)set1(rc[w],M+1,R);
    up(w);
}
void query(int w=1,int L=1,int R=n){
    if(l<=L&&R<=r){
        if(pv){
            lc[ptr]=pv;rc[ptr]=w;
            up(ptr);
            pv=ptr++;
        }else pv=w;
        return;
    }
    dwn(w);
    int M=L+R>>1;
    if(l<=M)query(lc[w],L,M);
    if(r>M)query(rc[w],M+1,R);
}
int main(){
    n=input();m=input();
    build(1,n);
    while(m--){
        int op=input();
        l=input(),r=input();
        if(op==0){
            set0();
        }else if(op==1){
            ans=0;
            get1();
            set0();
            l=input(),r=input();
            set1();
        }else{
            pv=0,ptr=p;
            query();
            printf("%d\n",ms[pv]);
        }
    }
    return 0;
}
时间: 2024-12-20 01:09:32

bzoj4592 [Shoi2015]脑洞治疗仪的相关文章

【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

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

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

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

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<