【线段树】HDU 3397 Sequence operation 区间合并
操作
Change operations:
0 a b change all characters into '0's in [a , b]
1 a b change all characters into '1's in [a , b]
2 a b change all '0's into '1's and change all '1's into '0's in [a, b]
Output operations:
3 a b output the number of '1's in [a, b]
4 a b output the length of the longest continuous '1' string in [a , b]
不太熟悉异或操作
用两种标记 col表示 区间变成0/1 。 ox表示 区间异或
0 1 操作跟普通线段树一样
异或操作须要 ox[rt]^=1;
......搞了一个晚上 错这里了..
4 操作普通的区间合并啦
lsum记录左边開始连续的1的个数 rsum记录右边開始连续的1的个数
zero就记录连续的0啦
还有在延迟的时候须要先pushdown col标记 再 pushdown ox标记
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define IN freopen ("in.txt" , "r" , stdin);
#define OUT freopen ("out.txt" , "w" , stdout);
typedef long long LL;
const int MAXN = 100110;//点数的最大值
const int MAXM = 20006;//边数的最大值
const int INF = 11521204;
const int mod=1000000007;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int num1[MAXN<<2],num2[MAXN<<2],ans[MAXN];
int sum[MAXN<<2],lsum[MAXN<<2],rsum[MAXN<<2];
int zero[MAXN<<2],lzero[MAXN<<2],rzero[MAXN<<2];
int col[MAXN<<2],ox[MAXN<<2];
void pushup(int rt,int m)
{
int lx=m-(m>>1);
int rx=(m>>1);
//1的向上更新
lsum[rt]=lsum[rt<<1];
rsum[rt]=rsum[rt<<1|1];
if(lsum[rt]==lx) lsum[rt]+=lsum[rt<<1|1];
if(rsum[rt]==rx) rsum[rt]+=rsum[rt<<1];
sum[rt]=max(max(sum[rt<<1],sum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]);
//0的向上更新
lzero[rt]=lzero[rt<<1];
rzero[rt]=rzero[rt<<1|1];
if(lzero[rt]==lx) lzero[rt]+=lzero[rt<<1|1];
if(rzero[rt]==rx) rzero[rt]+=rzero[rt<<1];
zero[rt]=max(max(zero[rt<<1],zero[rt<<1|1]),rzero[rt<<1]+lzero[rt<<1|1]);
//总数的更新
num1[rt]=num1[rt<<1]+num1[rt<<1|1];
num2[rt]=num2[rt<<1]+num2[rt<<1|1];
}
void pushdown(int rt,int m,int l,int r)
{
if(col[rt]!=-1)
{
ox[rt<<1]=ox[rt<<1|1]=0;
col[rt<<1]=col[rt<<1|1]=col[rt];
sum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=col[rt]?m-(m>>1):0;
sum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=col[rt]?m>>1:0;
zero[rt<<1]=lzero[rt<<1]=rzero[rt<<1]=col[rt]?0:m-(m>>1);
zero[rt<<1|1]=lzero[rt<<1|1]=rzero[rt<<1|1]=col[rt]?0:m>>1;
num1[rt<<1]=col[rt]? m-(m>>1):0;
num2[rt<<1]=col[rt]?0:m-(m>>1);
num1[rt<<1|1]=col[rt]?m>>1:0;
num2[rt<<1|1]=col[rt]? 0:m>>1;
col[rt]=-1;
}
if(ox[rt])
{
ox[rt<<1]^=1;
ox[rt<<1|1]^=1;
swap(sum[rt<<1],zero[rt<<1]);
swap(sum[rt<<1|1],zero[rt<<1|1]);
swap(lsum[rt<<1],lzero[rt<<1]);
swap(lsum[rt<<1|1],lzero[rt<<1|1]);
swap(rsum[rt<<1],rzero[rt<<1]);
swap(rsum[rt<<1|1],rzero[rt<<1|1]);
swap(num1[rt<<1],num2[rt<<1]);
swap(num1[rt<<1|1],num2[rt<<1|1]);
ox[rt]=0;
}
}
void build(int l,int r,int rt)
{
col[rt]=-1;
ox[rt]=0;
if(l==r)
{
scanf("%d",&num1[rt]);
if(num1[rt])
{
num2[rt]=0;
sum[rt]=lsum[rt]=rsum[rt]=1;
zero[rt]=lzero[rt]=rzero[rt]=0;
}
else
{
sum[rt]=lsum[rt]=rsum[rt]=0;
zero[rt]=lzero[rt]=rzero[rt]=1;
num2[rt]=1;
}
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt,r-l+1);
}
void update(int L,int R,int c,int l,int r,int rt)//更新 0 1 2 分别表示区间更新为0 , 1。异或
{
if(L<=l&&r<=R)
{
if(c==2)//异或
{
swap(num1[rt],num2[rt]);//0 1 个数交换
swap(sum[rt],zero[rt]);
swap(lsum[rt],lzero[rt]);
swap(rsum[rt],rzero[rt]);
ox[rt]^=1;
}
else
{
sum[rt]=lsum[rt]=rsum[rt]=c==1?r-l+1:0;
zero[rt]=lzero[rt]=rzero[rt]=c==1? 0:r-l+1;
num1[rt]=c==1?r-l+1:0;
num2[rt]=c==1?0:r-l+1;
col[rt]=c;
ox[rt]=0;
}
return ;
}
int m=(l+r)>>1;
pushdown(rt,r-l+1,l,r);
if(L<=m) update(L,R,c,lson);
if(m<R) update(L,R,c,rson);
pushup(rt,r-l+1);
}
int query1(int L,int R,int l,int r,int rt)//输出1的个数
{
if(L<=l&&r<=R)
{
return num1[rt];
}
int m=(l+r)>>1,res=0;
pushdown(rt,r-l+1,l,r);
if(L<=m) res+=query1(L,R,lson);
if(m<R) res+=query1(L,R,rson);
return res;
}
int query2(int L,int R,int l,int r,int rt)//输出连续的
{
if(L<=l&&r<=R)
{
return sum[rt];
}
int m=(l+r)>>1,res=0;
pushdown(rt,r-l+1,l,r);
if(L<=m) res=max(res, query2(L,R,lson));
if(m<R) res=max(res,query2(L,R,rson));
res = max(res, min(m-L+1, rsum[rt<<1])+min(R-m, lsum[rt<<1|1]));
return res;
}
int main()
{
int n,m,t;
//IN;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
build(1,n,1);
while(m--)
{
int a,b,c;
scanf("%d%d%d",&c,&a,&b);
a++,b++;
if(c <=2)
update(a,b,c,1,n,1);
else
{
if(c==3)
printf("%d\n",query1(a,b,1,n,1));
else printf("%d\n",query2(a,b,1,n,1));
}
}
}
return 0;
}
/*
1
4 3
0 0 1 1
1 1 2
2 1 2
3 1 1
*/
【线段树】HDU 3397 Sequence operation 区间合并的更多相关文章
- HDU 3397 Sequence operation(线段树)
HDU 3397 Sequence operation 题目链接 题意:给定一个01序列,有5种操作 0 a b [a.b]区间置为0 1 a b [a,b]区间置为1 2 a b [a,b]区间0变 ...
- hdu 3397 Sequence operation (线段树 区间合并 多重标记)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意: 给你一串01串,有5种操作 0. 区间全部变为0 1.区间全部变为1 2.区间异或 3.询问 ...
- 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(线段树:区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给你一个长度为n的0,1序列,支持下列五种操作, 操作0(0 a b):将a到b这个区间的 ...
- HDU 3397 Sequence operation(区间合并 + 区间更新)
题目链接:pid=3397">http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给定n个数,由0,1构成.共同拥有5种操作. 每一个操 ...
- hdu 3397 Sequence operation(很有意思的线段树题)
Sequence operation Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- HDU 3308 LCIS (线段树·单点更新·区间合并)
题意 给你一个数组 有更新值和查询两种操作 对于每次查询 输出相应区间的最长连续递增子序列的长度 基础的线段树区间合并 线段树维护三个值 相应区间的LCIS长度(lcis) 相应区间以左 ...
- HDU 1540 Tunnel Warfare 平衡树 / 线段树:单点更新,区间合并
Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Lim ...
- 线段树 HDU 3397(真)
5 种操作 0 1 然后 异或 似乎这种2个更新的先后每次都搞不清 覆盖有覆盖就可以不异或 也不知道为什么 #include<stdio.h> #include<string.h& ...
随机推荐
- XP下安装Centos 6.4 双系统 :Linux系统分区及挂载点,关键引导程序启动设置
一.关于Linux的分区情况 虽然硬盘分区表中最多能存储四个分区,但我们实际使用时一般只分为两个分区,一个是主分区(Primary Partion)一个是扩展分区(extended partition ...
- zookeeper【1】配置管理
为什么要用统一配置? 我们做项目时用到的配置比如数据库配置等...我们都是写死在项目里面,如果需要更改,那么也是的修改配置文件然后再投产上去,那么问题来了,如果做集群的呢,有100台机器,这时候做修改 ...
- Codeforces Round #356 (Div. 2) A. Bear and Five Cards 水题
A. Bear and Five Cards 题目连接: http://www.codeforces.com/contest/680/problem/A Description A little be ...
- Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) D. Bear and Two Paths 构造
D. Bear and Two Paths 题目连接: http://www.codeforces.com/contest/673/problem/D Description Bearland has ...
- Illegal instruction错误的定位---忽略编译期警告的代价
在原计算机的linux c++程序可以正确跑起来,但是换了一台机器运行时出现致命错误,程序直接当掉,错误提示如下: Illegal instruction (core dumped) 造成改错的主要原 ...
- windows下git命令的使用
一.写在前面 关于git,出于自己的爱好,前段时间玩了一下,也自己上网查了一下资料,现简单记录一下,以备查看. 当然,本文并不是介绍配置git服务器的文章,而是以github服务器作为git的远程仓库 ...
- Unity3D中的UnitySendMessage方法的使用
UnitySendMessage(“string”,“string”, ***),这是方法,我们至少需要传入两个参数,第一个参数为unity中的一个gameobject名称,第二个参数为这个gameo ...
- 向USB设备发送SCSI命令
http://bbs3.driverdevelop.com/simple/?t84347.html { BOOL status = ; DWORD accessMode = , shareMode = ...
- 第一次ACM赛后总结及感悟
2014 "嘉杰信息"杯 ACM/ICPC湖南程序设计邀请赛暨第六届湘潭程序设计比赛 赛后总结,尽管已经是大二第二学期了,这却是我的第一次真正的ACM比赛经历,大一尽管说就已经进了 ...
- Android的基本常用的短信操作
1.调用系统发送短信界面(传入手机号码+短信内容) 2.隐藏发送短信(指定号码指定内容)(这里隐藏只是没有反写入数据库) 3.获得收件箱接收到的短信 4.Android屏蔽新短信通知提示信息:(Con ...