考虑需要资瓷哪些操作:区间赋值为0;统计区间1的个数;将区间前k个0变为1;询问区间最长全0子串。于是线段树维护区间1的个数、0的个数、最长前缀后缀全0子串即可。稍微困难的是用一个log实现将区间前k个0变为1,线段树上二分尽量往左边改即可,可以令修改函数返回值为剩余能改的1的个数。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 200010
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int n,m,L[N<<],R[N<<];
struct data{int sum0,sum1,pre,suf,len,lazy;
}tree[N<<];
void update(int k,int x)
{
if (x==)
{
tree[k].sum0=tree[k].pre=tree[k].suf=tree[k].len=R[k]-L[k]+;
tree[k].sum1=;
}
else
{
tree[k].sum0=tree[k].pre=tree[k].suf=tree[k].len=;
tree[k].sum1=R[k]-L[k]+;
}
tree[k].lazy=x;
}
void up(int k)
{
tree[k].sum0=tree[k<<].sum0+tree[k<<|].sum0;
tree[k].sum1=tree[k<<].sum1+tree[k<<|].sum1;
if (tree[k<<].pre==R[k<<]-L[k<<]+) tree[k].pre=tree[k<<].pre+tree[k<<|].pre;
else tree[k].pre=tree[k<<].pre;
if (tree[k<<|].suf==R[k<<|]-L[k<<|]+) tree[k].suf=tree[k<<|].suf+tree[k<<].suf;
else tree[k].suf=tree[k<<|].suf;
tree[k].len=max(max(tree[k<<].len,tree[k<<|].len),tree[k<<].suf+tree[k<<|].pre);
}
void down(int k)
{
update(k<<,tree[k].lazy);
update(k<<|,tree[k].lazy);
tree[k].lazy=-;
}
void build(int k,int l,int r)
{
L[k]=l,R[k]=r;tree[k].lazy=-;
if (l==r) {tree[k].sum1=;return;}
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
up(k);
}
void modify(int k,int l,int r)
{
if (L[k]==l&&R[k]==r) {update(k,);return;}
if (~tree[k].lazy) down(k);
int mid=L[k]+R[k]>>;
if (r<=mid) modify(k<<,l,r);
else if (l>mid) modify(k<<|,l,r);
else modify(k<<,l,mid),modify(k<<|,mid+,r);
up(k);
}
int calc(int k,int l,int r)
{
if (L[k]==l&&R[k]==r) return tree[k].sum1;
if (~tree[k].lazy) down(k);
int mid=L[k]+R[k]>>;
if (r<=mid) return calc(k<<,l,r);
else if (l>mid) return calc(k<<|,l,r);
else return calc(k<<,l,mid)+calc(k<<|,mid+,r);
}
int query(int k,int l,int r)
{
if (L[k]==l&&R[k]==r) return tree[k].len;
if (~tree[k].lazy) down(k);
int mid=L[k]+R[k]>>;
if (r<=mid) return query(k<<,l,r);
else if (l>mid) return query(k<<|,l,r);
else return max(max(query(k<<,l,mid),query(k<<|,mid+,r)),min(tree[k<<].suf,mid-l+)+min(tree[k<<|].pre,r-mid));
}
int paint(int k,int l,int r,int x)
{
if (!x) return ;
if (L[k]==l&&R[k]==r&&x>=tree[k].sum0) {x-=tree[k].sum0;update(k,);return x;}
if (~tree[k].lazy) down(k);
int mid=L[k]+R[k]>>;
if (r<=mid) x=paint(k<<,l,r,x);
else if (l>mid) x=paint(k<<|,l,r,x);
else
{
int t=paint(k<<,l,mid,x);
if (t>=) x=paint(k<<|,mid+,r,t);
else x=;
}
up(k);
return x;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4592.in","r",stdin);
freopen("bzoj4592.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
build(,,n);
while (m--)
{
int op=read(),l=read(),r=read();
if (op==) modify(,l,r);
else if (op==)
{
int x=read(),y=read();
int k=calc(,l,r);
modify(,l,r);
paint(,x,y,k);
}
else printf("%d\n",query(,l,r));
}
return ;
}

BZOJ4592 SHOI2015脑洞治疗仪(线段树)的更多相关文章

  1. [BZOJ4592][SHOI2015]脑洞治疗仪(线段树)

    线段树基础操作题,唯一需要思考下的是将区间的前k个0覆盖为1. 线段树上二分,先递归到左子树覆盖,回溯时返回还剩多少个0未被覆盖,在根据这个信息递归到右子树.注意特判k=0的情况. 要维护的信息有:区 ...

  2. 【BZOJ4592】[Shoi2015]脑洞治疗仪 线段树

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

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

    4592: [Shoi2015]脑洞治疗仪 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 69  Solved: 38[Submit][Status] ...

  4. BZOJ 4592 SHOI2015 脑洞治疗仪 线段树

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4592 题意概述:需要维护一个01序列A,一开始A全部都是1.支持如下操作: 1.将区间[l ...

  5. [bzoj4592] [Shoi2015]脑洞治疗仪

    题面无法直视系列. 中规中矩的线段树题. 涉及的操作有:区间赋值为0,计算区间内1的个数,区间赋值为1,求区间内最大的连续的1的个数. #include<cstdio> #include& ...

  6. 2019.01.19 bzoj4592: [Shoi2015]脑洞治疗仪(ODT)

    传送门 ODT水题. 支持区间01赋值,区间填补(把区间[l,r][l,r][l,r]从左往右数kkk个1都变成0),区间查询最长连续1个数. 思路: 区间填补操作感觉不是很好弄,写线段树的神仙可以套 ...

  7. bzoj 4592(洛谷 4344) [Shoi2015]脑洞治疗仪——线段树上二分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4592 1操作就是用线段树来二分找到第一个有 k 个0的位置. 在洛谷上A了,与暴力和网上题解 ...

  8. bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪

    http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...

  9. 【题解】Luogu P4344 [SHOI2015]脑洞治疗仪

    原题传送门:P4344 [SHOI2015]脑洞治疗仪 前置芝士:珂朵莉树 窝博客里对珂朵莉树的介绍 没什么好说的自己看看吧 珂朵莉树好题啊 我一开始一直Re65 后来重构代码就ac了,或许是rp问题 ...

随机推荐

  1. linux服务基础之ftp服务

    ftp是一种文件传输协议,我们以redhat6.9为服务器系统,来介绍一下ftp服务器,这里我们先介绍一下ftp协议工作的原理 ftp协议可以在不同类型的计算机之间传输文件,工作流程大致为 1:客户机 ...

  2. SpringBoot向outlook发送邮件

    首先要登陆outlook邮箱,点击设置滑到最下面选择完整设置 进入后选择邮件->同步电子邮件 打开pop如上设置 下面是我的application.propertis设置 请填上自己的邮箱名与密 ...

  3. jQuery的封装

    封装,最简单的效果就是一个效果你可以重复的去调用   本来前端之路时间不是很长,但是对封装还是有一点点自己个人的理解,曾经踩过的坑也不在少数,最后总结出我个人风格的封装,听一位大神指点过,每个人都有属 ...

  4. 第一次使用Git上传本地项目到github

    看了好多帖子,终于在混乱中找到自己适合的方法......自我感觉这个比较简单. 先安装本地git,官方下载地址:http://git-scm.com/download/  根据你自己的系统 下载对应版 ...

  5. 深度剖析HBase负载均衡和性能指标

    深度剖析HBase负载均衡和性能指标 在分布式系统中,负载均衡是一个非常重要的功能,HBase通过Region的数量实现负载均衡,即通过hbase.master.loadbalancer.class实 ...

  6. ctf题目writeup(7)

    2019.2.10 过年休息归来,继续做题. bugku的web题,地址:https://ctf.bugku.com/challenges 1. http://123.206.87.240:8002/ ...

  7. 嵌入式linux系统移植(一)

    内容:   交叉编译环境   bootloader功能子系统   内核核心子系统   文件系统子系统要点:  搭建交叉编译环境  bootloader的选择和移植  kernel的配置.编译.移植和调 ...

  8. 第三章 最简单的C程序设计——顺序程序设计

    一.数据的表现形式及其运算 1.常量和变量 在计算机高级语言中,数据有两种表现形式:常量和变量. 1.1.常量 在程序运行过程中,其值不能被改变的量称为常量.如:5,6,32,0.111. 数值常量就 ...

  9. Python3爬虫(十一) 爬虫与反爬虫

    Infi-chu: http://www.cnblogs.com/Infi-chu/ 一.重要概念 二.爬虫反爬虫进化论

  10. codevs 1214 线段覆盖/1643 线段覆盖 3

    1214 线段覆盖/1214 线段覆盖  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold       题目描述 Description 给定x轴上的N(0< ...