[题目链接]

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. DispatcherServlet url-pattern中 /、/*、*.do中的区别与作用

    DispatcherServlet url-pattern中 /./*.*.do中的区别与作用 "/'表示匹配所有请求(其中包含除.jsp和.jspx外的所有后缀). 如果不配置静态资源,它 ...

  2. T1013 求先序排列 codevs

    http://codevs.cn/problem/1013/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Descr ...

  3. openURL

    在iOS开发中,经常需要调用其它App,如拨打电话.发送邮件等.UIApplication:openURL:方法是实现这一目的的 在iOS开发中,经常需要调用其它App,如拨打电话.发送邮件等.UIA ...

  4. 单点登录CAS-Demo

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 1安全证书配置 2部署服务端CAS-Server 3部署CAS-Client 4测试SSO   1,安全证书配置 CAS默认 ...

  5. Android入门常见问题

    前言: 眼下非常多人入门用android studio,可是我觉得这是 一个不好的開始. 一个集成的软件,不用你去部署.那么你就好难去学习究竟层的东西. 以后的问题时.问题所在还是在底层,就像&quo ...

  6. Koala - 使用

    几天项目又加紧,样式想写又太慢! 下载考拉:http://pc6.dun.123ch.cn/download/koala%E7%BC%96%E8%AF%91%E5%B7%A5%E5%85%B7_30@ ...

  7. Android手机输入法按键监听-dispatchKeyEvent

    近期在项目开发中遇到一个关于手机输入键盘的坑.特来记录下. 应用场景: 项目中有一个界面是用viewpaper加三个fragment写的,当中viewpaper被我屏蔽了左右滑动,上面有三个点击按钮, ...

  8. PHP读取excel(4)

    这一小节内容主要是PHPExcel读取少量excel数据,具体代码如下: <?php //数据较少的时候,一次性读取出来放到数组里 header("Content-Type:text/ ...

  9. mysql语法、特殊符号及正則表達式的使用

    http://blog.csdn.net/pipisorry/article/details/46773545 sql语言 结构化的查询语言.(Structured Query Language),是 ...

  10. IOS 获取设备本地音视频

    1.检索音视频 PHFetchOptions *allPhotosOptions; @property (nonatomic, strong) PHFetchResult *assetsFetchRe ...