BZOJ4592 SHOI2015脑洞治疗仪(线段树)
考虑需要资瓷哪些操作:区间赋值为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脑洞治疗仪(线段树)的更多相关文章
- [BZOJ4592][SHOI2015]脑洞治疗仪(线段树)
线段树基础操作题,唯一需要思考下的是将区间的前k个0覆盖为1. 线段树上二分,先递归到左子树覆盖,回溯时返回还剩多少个0未被覆盖,在根据这个信息递归到右子树.注意特判k=0的情况. 要维护的信息有:区 ...
- 【BZOJ4592】[Shoi2015]脑洞治疗仪 线段树
[BZOJ4592][Shoi2015]脑洞治疗仪 Description 曾经发明了自动刷题机的发明家SHTSC又公开了他的新发明:脑洞治疗仪--一种可以治疗他因为发明而日益增大的脑洞的神秘装置. ...
- 【BZOJ-4592】脑洞治疗仪 线段树
4592: [Shoi2015]脑洞治疗仪 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 69 Solved: 38[Submit][Status] ...
- BZOJ 4592 SHOI2015 脑洞治疗仪 线段树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4592 题意概述:需要维护一个01序列A,一开始A全部都是1.支持如下操作: 1.将区间[l ...
- [bzoj4592] [Shoi2015]脑洞治疗仪
题面无法直视系列. 中规中矩的线段树题. 涉及的操作有:区间赋值为0,计算区间内1的个数,区间赋值为1,求区间内最大的连续的1的个数. #include<cstdio> #include& ...
- 2019.01.19 bzoj4592: [Shoi2015]脑洞治疗仪(ODT)
传送门 ODT水题. 支持区间01赋值,区间填补(把区间[l,r][l,r][l,r]从左往右数kkk个1都变成0),区间查询最长连续1个数. 思路: 区间填补操作感觉不是很好弄,写线段树的神仙可以套 ...
- bzoj 4592(洛谷 4344) [Shoi2015]脑洞治疗仪——线段树上二分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4592 1操作就是用线段树来二分找到第一个有 k 个0的位置. 在洛谷上A了,与暴力和网上题解 ...
- bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪
http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...
- 【题解】Luogu P4344 [SHOI2015]脑洞治疗仪
原题传送门:P4344 [SHOI2015]脑洞治疗仪 前置芝士:珂朵莉树 窝博客里对珂朵莉树的介绍 没什么好说的自己看看吧 珂朵莉树好题啊 我一开始一直Re65 后来重构代码就ac了,或许是rp问题 ...
随机推荐
- php判断某个数是素数的3种方法
什么是素数? 质数又称素数.一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数:否则称为合数.(注:1不是素数.) 方法一: 基本方法,——计数方法. $num = 7; $n = ...
- 转:java中的定时任务
引自:http://www.cnblogs.com/wenbronk/p/6433178.html java中的定时任务, 使用java实现有3种方式: 1, 使用普通thread实现 @Test p ...
- js继承的几种方法和es6继承方法
一.原型链继 1.基本思想 利用原型链来实现继承,超类的一个实例作为子类的原型 2.具体实现 function F() {} //原型属性,原型方法: ...
- es6几个新增语法的使用----数组
//数组的累加方法 let arr=[1,2,3]; let sum=arr.reduce((prev,cur)=>{ return prev+cur; }) console.log(sum)/ ...
- Laravel POST请求API接口 使用validate表单验证返回欢迎页
突然遇到的问题 就是使用Laravel进行开发API接口的时候 发现在表单验证不通过的时候返回了登录页 猜测问题应该是因为表单验证失败后进行了重定向导致的 因为返回状态码200 网上找了好久没找到 ...
- php 电商系统SKU库存设计
sku 全称为:Stock Keeping Unit,是库存进出计量的基本单元. 我们一般会在电商网站基本都会看到 比如淘宝,JD 淘宝和JD的 方式可能不一样,因为我不清楚他们具体是如何设计的, J ...
- ruby 可枚举模块Enumerable
Enumerable模块提供了遍历,搜索,比较,排序等方法.如果我们自定义的类需要实现这些方法,必须实现一个each方法.如果需要使用max,min,sort等方法,因为这些方法是集合的元素之间的排序 ...
- 修复网站漏洞对phpmyadmin防止被入侵提权的解决办法
phpmyadmin是很多网站用来管理数据库的一个系统,尤其是mysql数据库管理的较多一些,最近phpmysql爆出漏洞,尤其是弱口令,sql注入漏洞,都会导致mysql的数据账号密码被泄露,那么如 ...
- Go web表单
package main import ( "fmt" "html/template" "log" "net/http" ...
- Codeforces Round #500 (Div. 2) BC
CodeForces 1013B And CodeForces 1013C Photo of The Sky B 可以发现只有一次与操作是有意义的,所以答案只有-1,0,1,2四种情况 #inclu ...