[题目链接]

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. 漫话最小割 part1

    codeforces 724D [n个城市每个城市有一个特产的产出,一个特产的最大需求.当i<j时,城市i可以运最多C个特产到j.求所有城市可以满足最大的需求和] [如果直接最大流建图显然会T. ...

  2. Codeforces 424 C. Magic Formulas

    xor是满足交换律的,展开后发现仅仅要能高速求出 [1mod1....1modn],....,[nmod1...nmodn]的矩阵的xor即可了....然后找个规律 C. Magic Formulas ...

  3. libxml/HTMLparser.h file not found

    在导入asihttprequest包时出问题导入了libxml2.dylib.可是却提示libxml/HTMLparser.h file not found. 这是由于你的开发环境默认的路径无法找到这 ...

  4. hive cli 启动缓慢问题

    hive-0.13.1启动缓慢的原因 发现时间主要消耗在以下3个地方: 1. hadoopjar的时候要把相关的jar包上传到hdfs中(这里大概消耗5s,hive0.11一样,这个地方不太好优化) ...

  5. 数组index

    1. 数组index与数组名的位置关系     a[b] = *(a + b) = *(b + a) = b[a] int a[5] = {1, 2, 3, 4, 5}; printf("% ...

  6. Redis HyperLogLog及应用

    参考:http://www.runoob.com/redis/redis-hyperloglog.html Redis 在 2.8.9 之后的版本中,添加了 HyperLogLog 结构,用来做基数统 ...

  7. Android_Service详解及实例

    转自:http://blog.csdn.net/guolin_blog/article/details/11952435    http://blog.csdn.net/guolin_blog/art ...

  8. TC SRM 582 DIV 2

    Rating又跌了,第二个题,没想好就乱开始乱写了.. 我写乱搞贪心,没过...如果总人数很多judge函数写的不好,DIV2数据很水,直接暴力就行. #include <cstring> ...

  9. Mac OS用minikube安装单节点kubernetes

    参考 https://kubernetes.io/docs/tasks/tools/install-minikube/ https://github.com/linianhui/code/blob/m ...

  10. redis中的五种基本的数据结构

    1 String 基本的数据类型. 2 list 2.1 将元素放入一个list中 rpush mylist A rpush mylist B rpush mylist A 如果mylist本来是不存 ...