[题目链接]

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. 阻塞IO下的echo回显实验

    我们只关心代码中的业务逻辑和底层阻塞原因 客户端代码 发送数据 std::string message(len, 'S'); int nw = stream->sendAll(message.c ...

  2. CAN 和 CANopen的区别和联系

    1.CAN与CANopen的共同点与不同点:  CAN只定义了物理层与链路层,而没有定义用户层,用户可根据自己的需要定义一些网络上的通信约定:  CANopen是在CAN的基础上定义了用户层,即规定了 ...

  3. luogu P1704 寻找最优美做题曲线

    题目背景 nodgd是一个喜欢写程序的同学,前不久(好像还是有点久了)洛谷OJ横空出世,nodgd同学当然第一时间来到洛谷OJ刷题.于是发生了一系列有趣的事情,他就打算用这些事情来出题恶心大家-- 题 ...

  4. Java中ArrayList类

    ArratList 类:存放同一数据类型容器(只能为引用数据类型,因实际其内部存放的是地址) 1.导入其所在包 import java.util.ArratList 2.创建对象 ArrayList& ...

  5. ffmpeg实时编码解码部分代码

    程序分为编码端和解码端,两端通过tcp  socket通信,编码端一边编码一边将编码后的数据发送给解码端.解码端一边接收数据一边将解码得到的帧显示出来. 代码中的编码端编码的是实时屏幕截图. 代码调用 ...

  6. 反混淆:恢复被OLLVM保护的程序

    译者序: OLLVM作为代码混淆的优秀开源项目,在国内主流app加固应用中也经常能看到它的身影,但是公开的分析研究资料寥寥.本文是Quarkslab团队技术博客中一篇关于反混淆的文章,对OLLVM项目 ...

  7. python中pymysql使用

    python中pymysql使用 https://blog.csdn.net/johline/article/details/69549131 import pymysql # 连接数据库 conne ...

  8. HDU 4857 topological_sort

    逃生 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission ...

  9. jquery 常用选择器 回顾 ajax() parent() parents() children() siblings() find() eq() has() filter() next()

    1. $.ajax() ajax 本身是异步操作,当需要将 异步 改为 同步时: async: false 2.parent()  父级元素  和  parents() 祖先元素 的区别 parent ...

  10. Android studio 升级,不用下载完整版,完美更新到2.0

    Android studio 2.0 公布已有一旦时间,据说,速度大大提高了.但是一直没有尝试更新,看到大家相继更新,所以迫不及待就准备更新,但是.更新之路确实异常坎坷.询问度娘,千奇百怪的问题接憧而 ...