[SHOI 2015] 脑洞治疗仪
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=4592
[算法]
对于操作1 , 我们首先查询区间[l0 , r0]中有多少个1 , 然后二分求出最大的x(x <= r1)使得[l1 , x]中0的个数 <= [l0 , r0]中1的个数
对于操作2 , 对于一段区间[l , r] , 我们将它分成[l , mid]和[mid + 1 , r]两个子区间 , 那么 , 最长连续的0的个数有三种情况 :
1. 在[l , mid]中 2. 在[mid + 1 , r]中 3. mid向前延伸最多的0的个数 + (mid + 1)向后延伸最多的0的个数
线段树维护即可
时间复杂度 : O(NlogN ^ 2)
[代码]
#include<bits/stdc++.h>
using namespace std;
#define MAXN 200010
typedef long long ll;
typedef long double ld;
const int inf = 1e9; int n , m; template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
template <typename T> inline void read(T &x)
{
T f = ; x = ;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = (x << ) + (x << ) + c - '';
x *= f;
} struct Segment_Tree
{
struct Node
{
int l , r;
int lm0 , rm0 , value , cnt;
int tag;
} a[MAXN << ];
inline void build(int index , int l , int r)
{
a[index].l = l , a[index].r = r;
a[index].cnt = r - l + ;
a[index].tag = -;
if (l == r) return;
int mid = (l + r) >> ;
build(index << , l , mid);
build(index << | , mid + , r);
}
inline void update(int x)
{
int l = a[x].l , r = a[x].r;
int mid = (l + r) >> ;
a[x].cnt = a[x << ].cnt + a[x << | ].cnt;
if (a[x << ].lm0 == mid - l + ) a[x].lm0 = mid - l + + a[x << | ].lm0;
else a[x].lm0 = a[x << ].lm0;
if (a[x << | ].rm0 == r - mid) a[x].rm0 = r - mid + a[x << ].rm0;
else a[x].rm0 = a[x << | ].rm0;
a[x].value = max(a[x << ].value , a[x << | ].value);
chkmax(a[x].value , a[x << ].rm0 + a[x << | ].lm0);
}
inline void pushdown(int index)
{
int l = a[index].l , r = a[index].r;
int mid = (l + r) >> ;
if (l == r) return;
if (a[index].tag == )
{
a[index << ].cnt = a[index << | ].cnt = ;
a[index << ].value = mid - l + ;
a[index << | ].value = r - mid;
a[index << ].lm0 = a[index << ].rm0 = mid - l + ;
a[index << | ].lm0 = a[index << | ].rm0 = r - mid;
a[index << ].tag = a[index << | ].tag = a[index].tag;
a[index].tag = -;
}
if (a[index].tag == )
{
a[index << ].cnt = mid - l + ;
a[index << | ].cnt = r - mid;
a[index << ].value = a[index << | ].value = ;
a[index << ].lm0 = a[index << ].rm0 = ;
a[index << | ].lm0 = a[index << | ].rm0 = ;
a[index << ].tag = a[index << | ].tag = a[index].tag;
a[index].tag = -;
}
}
inline void modify(int index , int l , int r)
{
if (a[index].l == l && a[index].r == r)
{
a[index].cnt = ;
a[index].lm0 = a[index].rm0 = r - l + ;
a[index].value = r - l + ;
a[index].tag = ;
return;
}
pushdown(index);
int mid = (a[index].l + a[index].r) >> ;
if (mid >= r) modify(index << , l , r);
else if (mid + <= l) modify(index << | , l , r);
else
{
modify(index << , l , mid);
modify(index << | , mid + , r);
}
update(index);
}
inline int queryA(int index , int l , int r)
{
if (a[index].l == l && a[index].r == r)
return a[index].cnt;
pushdown(index);
int mid = (a[index].l + a[index].r) >> ;
if (mid >= r) return queryA(index << , l , r);
else if (mid + <= l) return queryA(index << | , l , r);
else return queryA(index << , l , mid) + queryA(index << | , mid + , r);
}
inline int queryB(int index , int l , int r)
{
if (a[index].l == l && a[index].r == r)
return a[index].value;
pushdown(index);
int mid = (a[index].l + a[index].r) >> ;
if (mid >= r) return queryB(index << , l , r);
else if (mid + <= l) return queryB(index << | , l , r);
{
int ret = max(queryB(index << , l , mid) , queryB(index << | , mid + , r));
chkmax(ret , min(mid - l + , a[index << ].rm0) + min(r - mid , a[index << | ].lm0));
return ret;
}
}
inline void change(int index , int l , int r)
{
if (l > r) return;
if (a[index].l == l && a[index].r == r)
{
a[index].cnt = r - l + ;
a[index].lm0 = a[index].rm0 = a[index].value = ;
a[index].tag = ;
return;
}
pushdown(index);
int mid = (a[index].l + a[index].r) >> ;
if (mid >= r) change(index << , l , r);
else if (mid + <= l) change(index << | , l , r);
else
{
change(index << , l , mid);
change(index << | , mid + , r);
}
update(index);
}
} SGT; int main()
{ read(n); read(m);
SGT.build( , , n);
for (int i = ; i <= m; i++)
{
int type;
read(type);
if (type == )
{
int x , y;
read(x); read(y);
SGT.modify( , x , y);
} else if (type == )
{
int l0 , r0 , l1 , r1;
read(l0); read(r0); read(l1); read(r1);
int cnt = SGT.queryA( , l0 , r0);
SGT.modify( , l0 , r0);
int l = l1 , r = r1 , loc = ;
while (l <= r)
{
int mid = (l + r) >> ;
if ((mid - l1 + ) - SGT.queryA( , l1 , mid) <= cnt)
{
loc = mid;
l = mid + ;
} else r = mid - ;
}
SGT.change( , l1 , loc);
} else
{
int l , r;
read(l); read(r);
printf("%d\n" , SGT.queryB( , l , r));
}
} return ;
}
[SHOI 2015] 脑洞治疗仪的更多相关文章
- 【BZOJ-4592】脑洞治疗仪 线段树
4592: [Shoi2015]脑洞治疗仪 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 69 Solved: 38[Submit][Status] ...
- 【题解】Luogu P4344 [SHOI2015]脑洞治疗仪
原题传送门:P4344 [SHOI2015]脑洞治疗仪 前置芝士:珂朵莉树 窝博客里对珂朵莉树的介绍 没什么好说的自己看看吧 珂朵莉树好题啊 我一开始一直Re65 后来重构代码就ac了,或许是rp问题 ...
- 【BZOJ4592】[Shoi2015]脑洞治疗仪 线段树
[BZOJ4592][Shoi2015]脑洞治疗仪 Description 曾经发明了自动刷题机的发明家SHTSC又公开了他的新发明:脑洞治疗仪--一种可以治疗他因为发明而日益增大的脑洞的神秘装置. ...
- 【SHOI2015】脑洞治疗仪(恶心的线段树,区间最大子段和)
题目描述: 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个 01 序列.11代表这个位 ...
- [SHOI2015]脑洞治疗仪(恶心的线段树,区间最大子段和)
题目描述: 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪--一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个 01 序列.11代表这个位 ...
- loj #2037. 「SHOI2015」脑洞治疗仪
#2037. 「SHOI2015」脑洞治疗仪 题目描述 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见 ...
- 洛谷P4344 [SHOI2015]脑洞治疗仪(珂朵莉树)
传送门 看到区间推倒……推平就想到珂朵莉树 挖脑洞直接assign,填坑先数一遍再assign再暴力填,数数的话暴力数 //minamoto #include<iostream> #inc ...
- 【bzoj4592】[Shoi2015]脑洞治疗仪
由于脑洞的序列不会改变,考虑用线段树维护区间内sum,左边0的个数,右边0的个数,区间内最大脑洞.对于查询l~r最大脑洞可以将l~r分成logn个区间,总复杂度O(nlogn). #include&l ...
- 题解 P4344 【[SHOI2015]脑洞治疗仪】
前言 这道题目呢,看上去很难,实际上我们可以用线段树解决这道题目. 正文 我们维护 sum.len.tag.lmax.rmax.ans. sum 就是这段区间非脑洞的个数 len 就是这段区间的长度 ...
随机推荐
- css3 画三角形
/*箭头向上*/ .arrow-up { width:0; height:0; border-left:20px solid transparent; border-right:20px solid ...
- JS实现限行
一.JS代码实现 1. 机动车辆限行如下图所示: 具体详情请访问:http://www.bjjtgl.gov.cn/zhuanti/10weihao/index.html 2.JS代码实现 <! ...
- linux svn配置hooks
先创建仓库: svnadmin create /data/svn/my.com 再配置权限: #cd /data/svn/my.com/conf/ #vim svnserve.conf 配置 [gen ...
- Javascript:如何调用全局变量?
怎样使用全局变量呢? window.globalVariableName 参考: https://blog.csdn.net/zyz511919766/article/details/7276089
- excel 分类汇总函数
1.先用数组公式对单元格区域 B3:B39 ,进行提取去重复非空调单元格信息.单元格B52数组公式: =INDIRECT(TEXT(MIN(IF((COUNTIF(B$51:B51,B$3:B$39) ...
- win7系统使用engine进行开发报错,“未能加载文件或程序集”
http://www.gisall.com/wordpress/?p=7161 使用vs2010加 arcengine 开发winfrom应用,新建了uc,拖了几个控件后,编译,报未能加载文件或程序集 ...
- 【转】fedora和ubuntu开启ssh
fedora和ubuntu开启ssh 1小时前 ubuntu开启SSH服务 SSH分客户端openssh-client和openssh-server如果你只是想登陆别的机器的SSH只需要安装opens ...
- WSDL4J解析WSDL文件方法
利用wsdl4j解析WSDL文件 工具:wsdl4j1.6 解析wsdl文件是axis1.4的服务wsdl文件 wsdl文件: <?xml version="1.0" enc ...
- 如何推断一个P2P平台是否靠谱?
推断一个站点,是否靠谱.是有规律可循的.P2P平台算是个新兴的电商类站点. 网上欺诈类的站点.不限于P2P,实在是太多了,真的有必要总结下最关键的几个靠谱指标. 最关键的2个 1.创始人和 ...
- UVa567_Risk(最短路)(小白书图论专题)
解题报告 option=com_onlinejudge&Itemid=8&category=7&page=show_problem&problem=508"& ...