hdu 3397 Sequence operation (线段树 区间合并 多重标记)
链接;http://acm.hdu.edu.cn/showproblem.php?pid=3397
题意:
给你一串01串,有5种操作
0. 区间全部变为0
1.区间全部变为1
2.区间异或
3.询问区间1的个数
4.询问区间被最长连续1的长度
思路:
这5个操作都是比较基础的线段树操作,难点在于有两种修改操作,这类题之前也写过,之前是乘法和加法,这个是区间亦或和区间更新值,但是思路是可以借鉴的,我们要推出这两个操作的关系,这样才能维护好这两个标记,我们用两个标记:same , rev ,分别表示区间更新值和区间异或,那么向下更新的时候如果如果有same标记,清空当前区间的rev标记,简单维护下就好了,如果有rev标记,且有same标记,那么直接对same异或维护,如果没有same标记那么就维护下区间异或就好了。
写的超爽,一遍就a了,美滋滋,还以为又要找好久的错。。
实现代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
#define ll long long const int M = 1e5 + ;
int lsum1[M<<],rsum1[M<<],sum1[M<<];
int lsum0[M<<],rsum0[M<<],sum0[M<<];
int sum[M<<],same[M<<],rev[M<<];
int a[M]; void pushup(int l,int r,int rt){
mid;
sum[rt] = sum[rt<<] + sum[rt<<|];
lsum0[rt] = lsum0[rt<<]; lsum1[rt] = lsum1[rt<<];
rsum0[rt] = rsum0[rt<<|]; rsum1[rt] = rsum1[rt<<|];
if(lsum0[rt] == m-l+) lsum0[rt] += lsum0[rt<<|];
if(rsum0[rt] == r-m) rsum0[rt] += rsum0[rt<<];
if(lsum1[rt] == m-l+) lsum1[rt] += lsum1[rt<<|];
if(rsum1[rt] == r-m) rsum1[rt] += rsum1[rt<<];
sum0[rt] = max(max(sum0[rt<<],sum0[rt<<|]),lsum0[rt<<|]+rsum0[rt<<]);
sum1[rt] = max(max(sum1[rt<<],sum1[rt<<|]),lsum1[rt<<|]+rsum1[rt<<]);
} void swa(int len,int rt){
sum[rt] = len - sum[rt];
swap(lsum1[rt],lsum0[rt]);
swap(rsum1[rt],rsum0[rt]);
swap(sum1[rt],sum0[rt]);
} void pushdown(int l,int r,int rt){
mid;
if(same[rt]!=-){
rev[rt<<] = rev[rt<<|] = ;
same[rt<<] = same[rt<<|] = same[rt];
if(same[rt]){
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = m-l+;
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = r-m;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = ;
}
else{
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = ;
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = ;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = m-l+;
sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = r-m;
}
same[rt] = -;
}
if(rev[rt]){
if(same[rt<<] != -){
same[rt<<] ^= ;
if(same[rt<<]){
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = m-l+;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = ;
}
else{
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = ;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = m-l+;
}
}
else{
rev[rt<<] ^= ;
swa(m-l+,rt<<);
}
if(same[rt<<|] != -){
same[rt<<|] ^= ;
if(same[rt<<|]){
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = r-m;
sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = ;
}
else{
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = ;
sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = r-m;
}
}
else{
rev[rt<<|] ^= ;
swa(r-m,rt<<|);
}
rev[rt] = ;
}
} void build(int l,int r,int rt){
same[rt] = -; rev[rt] = ;
lsum1[rt] = rsum1[rt] = lsum0[rt] = rsum0[rt] = sum0[rt] = sum1[rt] = sum[rt] = ;
if(l == r){
if(a[l]){
lsum1[rt] = sum[rt] = sum1[rt] = rsum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
else {
sum1[rt] = sum[rt] = sum1[rt] = rsum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
return ;
}
mid ;
build(lson); build(rson);
pushup(l,r,rt);
} void update_same(int L,int R,int c,int l,int r,int rt){
if(L <= l&&R >= r){
rev[rt] = ;
same[rt] = c;
if(same[rt]){
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = r-l+;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
else{
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = r-l+;
}
return ;
}
pushdown(l,r,rt);
mid;
if(L <= m) update_same(L,R,c,lson);
if(R > m) update_same(L,R,c,rson);
pushup(l,r,rt);
} void update_rev(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
if(same[rt] != -){
same[rt] ^= ;
if(same[rt]){
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = r-l+;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
else{
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = r-l+;
}
}
else{
rev[rt] ^= ;
swa(r-l+,rt);
}
return ;
}
mid ;
pushdown(l,r,rt);
if(L <= m) update_rev(L,R,lson);
if(R > m) update_rev(L,R,rson);
pushup(l,r,rt);
} int query_sum(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
return sum[rt];
}
pushdown(l,r,rt);
mid;
int ret = ;
if(L <= m) ret += query_sum(L,R,lson);
if(R > m) ret += query_sum(L,R,rson);
return ret;
} int query_max(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
return sum1[rt];
}
pushdown(l,r,rt);
mid;
int ret = ;
if(L > m) return query_max(L,R,rson);
if(R <= m) return query_max(L,R,lson);
int t1 = query_max(L,R,lson);
int t2 = query_max(L,R,rson);
int ls = min(rsum1[rt<<],m-L+);
int rs = min(lsum1[rt<<|],R-m);
return max(max(t1,t2),ls+rs);
} int main()
{
int n,q,x,y,op,t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&q);
for(int i = ;i <= n;i ++)
scanf("%d",&a[i]);
build(,n,);
while(q--){
scanf("%d%d%d",&op,&x,&y);
x++; y++;
if(op == ){
update_same(x,y,,,n,);
}
else if(op == ){
update_same(x,y,,,n,);
}
else if(op == ){
update_rev(x,y,,n,);
}
else if(op == ){
printf("%d\n",query_sum(x,y,,n,));
}
else {
printf("%d\n",query_max(x,y,,n,));
}
}
}
return ;
}
hdu 3397 Sequence operation (线段树 区间合并 多重标记)的更多相关文章
- hdu 3397 Sequence operation 线段树 区间更新 区间合并
题意: 5种操作,所有数字都为0或1 0 a b:将[a,b]置0 1 a b:将[a,b]置1 2 a b:[a,b]中的0和1互换 3 a b:查询[a,b]中的1的数量 4 a b:查询[a,b ...
- hdu 3397 Sequence operation 线段树
题目链接 给出n个数, 每个数是0或1, 给5种操作, 区间变为1, 区间变为0, 区间0,1翻转, 询问区间内1的个数, 询问区间内最长连续1的个数. 需要将数组开成二维的, 然后区间0, 1翻转只 ...
- HDU 6638 - Snowy Smile 线段树区间合并+暴力枚举
HDU 6638 - Snowy Smile 题意 给你\(n\)个点的坐标\((x,\ y)\)和对应的权值\(w\),让你找到一个矩形,使这个矩阵里面点的权值总和最大. 思路 先离散化纵坐标\(y ...
- HDU 5316——Magician——————【线段树区间合并区间最值】
Magician Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- HDU 1540 Tunnel Warfare 线段树区间合并
Tunnel Warfare 题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少 思路:一个节点的最大连续区间由(左儿子的最大的连续区间,右儿子的最大连续区 ...
- Sequence operation(线段树区间多种操作)
Sequence operation Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- (简单) HDU 3308 LCIS,线段树+区间合并。
Problem Description Given n integers. You have two operations: U A B: replace the Ath number by B. ( ...
- hdu 4453 约会安排(线段树区间合并)
约会安排 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submis ...
- hdu 3308 LCIS(线段树区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=3308 LCIS Time Limit: 6000/2000 MS (Java/Others) ...
随机推荐
- ADO.NET分享
看到<c#从入门到精通(第三版)>书中对ado.net里几种方法打的比方,很有意思就发一下. 1)这张图中,把数据比作水,储存了大量数据. 2)Connection对象好像进水龙头,插在水 ...
- CF1056E Check Transcription 字符串哈希
传送门 暴力枚举\(0\)的长度,如果对应的\(1\)的长度也是一个整数就去check是否合法.check使用字符串哈希. 复杂度看起来是\(O(st)\)的,但是因为\(01\)两个数中数量较多的至 ...
- React-组件 & Props
React元素可以只是DOM标签 const element = <div />; React元素也可以是用户自定义的组件: const element = <Welcome nam ...
- 【iOS】build diff: /../Podfile.lock: No such file or directory
Github 上下载的开源项目,在 Xcode 打开运行后报了错,如图所示: 解决方法: 在工程设置中的 Build Phases 下删除 Check Pods Manifest.lock 及 Cop ...
- Python 学习 第四篇:动态类型模型
Python的变量不用声明,赋值之后就可以直接使用,类型是在运行过程中自动确定的,这就是动态类型模型.该模型把变量和对象设计成两个不同的实体,对象是存储数据的地方,对象的类型是由初始值自动决定的,而变 ...
- 止不住的裁员潮:看京东前员工吐槽——绩效打C还希望我好好干
昨天,京东裁员消息被证实,京东将在2019年末位淘汰10%的副总裁级别以上的高管. 在互联网职场交流社区,一名自称京东的员工如此吐槽:办完离职了心情大好,自由放飞,明天入职新公司,你给新员工打C,还希 ...
- C_数据结构_递归自己调用自己
# include <stdio.h> void f(int n) { ) printf("哈哈\n"); else f(n-i); } int main(void) ...
- <a>标签中href="javascript:;"** 为什么 style不用src**
&src/href <!--href 用于标示资源和文档关系,src 用于替换标签内容--> <img src="xxx.jpg"/> <sc ...
- python语言几个常见函数的使用
写代码,有如下变量,请按照要求实现每个功能: name = " Kobe Bean Bryant" a. 移除 name 变量对应的值左边的空格,并输出移除后的内容 name = ...
- 总结 推广app
扫一扫二维码即可安装使用我们的app,方便快捷. 电脑端下载地址:http://pan.baidu.com/s/1bocWPPX http://a.app.qq.com/o/simple.jsp?pk ...