[题目链接]

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] 脑洞治疗仪的更多相关文章

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

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

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

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

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

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

  4. 【SHOI2015】脑洞治疗仪(恶心的线段树,区间最大子段和)

    题目描述: 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个 01 序列.11代表这个位 ...

  5. [SHOI2015]脑洞治疗仪(恶心的线段树,区间最大子段和)

    题目描述: 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪--一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个 01 序列.11代表这个位 ...

  6. loj #2037. 「SHOI2015」脑洞治疗仪

    #2037. 「SHOI2015」脑洞治疗仪   题目描述 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见 ...

  7. 洛谷P4344 [SHOI2015]脑洞治疗仪(珂朵莉树)

    传送门 看到区间推倒……推平就想到珂朵莉树 挖脑洞直接assign,填坑先数一遍再assign再暴力填,数数的话暴力数 //minamoto #include<iostream> #inc ...

  8. 【bzoj4592】[Shoi2015]脑洞治疗仪

    由于脑洞的序列不会改变,考虑用线段树维护区间内sum,左边0的个数,右边0的个数,区间内最大脑洞.对于查询l~r最大脑洞可以将l~r分成logn个区间,总复杂度O(nlogn). #include&l ...

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

    前言 这道题目呢,看上去很难,实际上我们可以用线段树解决这道题目. 正文 我们维护 sum.len.tag.lmax.rmax.ans. sum 就是这段区间非脑洞的个数 len 就是这段区间的长度 ...

随机推荐

  1. grafana 安装 和 Nginx 、EL 联调

    https://blog.csdn.net/u010735147/article/details/80943593

  2. POJ 3694 (tarjan缩点+LCA+并查集)

    好久没写过这么长的代码了,题解东哥讲了那么多,并查集优化还是很厉害的,赶快做做前几天碰到的相似的题. #include <iostream> #include <algorithm& ...

  3. R必学包之dplyr

    http://www.360doc.com/content/17/1204/10/50223086_709726679.shtml

  4. Codeforces 864E Fire(DP)

    题目链接 Fire 题意 有n个物品,每个物品的挽救时间代价为ti, 消失时刻为di, 价值为pi. 如果要救某个物品,必须在他消失之前救出来. 同一时刻最多只能救一件物品. 当前耗时为当前已经救出的 ...

  5. jquery 实现鼠标点击div盒子移动功能

    // Start 窗口的拖动 var _move=false; //移动标记 var _x,_y; //鼠标离控件左上角的相对位置 $(document).ready(function(){ $(&q ...

  6. jquery 获取浏览器窗口的可视区域高度 宽度 滚动条高

    原文:http://www.open-open.com/code/view/1421827925437 alert($(window).height()); //可视区域高度 alert($(docu ...

  7. ViewPager 无限循环遇到的坑 viewpager.setOffscreenPageLimit(2);

    viewpager.setOffscreenPageLimit(limit);这个方法,是表示viewpage除了当前显示的页面外,左右个预加载的页面个数,也就是 为limit=2时表示当前一共加载了 ...

  8. 在windows Server 2008 R2server上使用infopath不能将表单公布到sharepoint server的问题处理。

    在server 2008 R2 中.你将做好的表单公布到Sharepoint 时候会报错: 这个情况在client是2008 R2 Server 就会出现这个结果. 在角色中启用桌面体验就可以

  9. 《python源代码剖析》笔记 Python的编译结果

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.python的运行过程 1)对python源码进行编译.产生字节码 2)将编译结果交给p ...

  10. ansible 基本命令学习与踩坑

    1. 命令行参数 -v,–verbose 详细模式,如果命令执行成功,输出详细的结果(-vv –vvv -vvvv) -i PATH,–inventory=PATH 指定host文件的路径,默认是在/ ...