考虑需要资瓷哪些操作:区间赋值为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. php判断某个数是素数的3种方法

    什么是素数? 质数又称素数.一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数:否则称为合数.(注:1不是素数.) 方法一: 基本方法,——计数方法. $num = 7; $n = ...

  2. 转:java中的定时任务

    引自:http://www.cnblogs.com/wenbronk/p/6433178.html java中的定时任务, 使用java实现有3种方式: 1, 使用普通thread实现 @Test p ...

  3. js继承的几种方法和es6继承方法

        一.原型链继     1.基本思想     利用原型链来实现继承,超类的一个实例作为子类的原型     2.具体实现     function F() {}     //原型属性,原型方法: ...

  4. es6几个新增语法的使用----数组

    //数组的累加方法 let arr=[1,2,3]; let sum=arr.reduce((prev,cur)=>{ return prev+cur; }) console.log(sum)/ ...

  5. Laravel POST请求API接口 使用validate表单验证返回欢迎页

    突然遇到的问题  就是使用Laravel进行开发API接口的时候  发现在表单验证不通过的时候返回了登录页 猜测问题应该是因为表单验证失败后进行了重定向导致的 因为返回状态码200 网上找了好久没找到 ...

  6. php 电商系统SKU库存设计

    sku 全称为:Stock Keeping Unit,是库存进出计量的基本单元. 我们一般会在电商网站基本都会看到 比如淘宝,JD 淘宝和JD的 方式可能不一样,因为我不清楚他们具体是如何设计的, J ...

  7. ruby 可枚举模块Enumerable

    Enumerable模块提供了遍历,搜索,比较,排序等方法.如果我们自定义的类需要实现这些方法,必须实现一个each方法.如果需要使用max,min,sort等方法,因为这些方法是集合的元素之间的排序 ...

  8. 修复网站漏洞对phpmyadmin防止被入侵提权的解决办法

    phpmyadmin是很多网站用来管理数据库的一个系统,尤其是mysql数据库管理的较多一些,最近phpmysql爆出漏洞,尤其是弱口令,sql注入漏洞,都会导致mysql的数据账号密码被泄露,那么如 ...

  9. Go web表单

    package main import ( "fmt" "html/template" "log" "net/http" ...

  10. Codeforces Round #500 (Div. 2) BC

    CodeForces 1013B And CodeForces 1013C  Photo of The Sky B 可以发现只有一次与操作是有意义的,所以答案只有-1,0,1,2四种情况 #inclu ...