费了我一天半的时间,到处debug,后来才发现,主要是建树的时候只在叶子节点对lazy1和lazy2进行初始化了,父节点都没初始化。。。晕。

  具体见代码吧。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#define lson rt<<1,L,mid
#define rson rt<<1|1,mid+1,R
/*
用两个lazy标记,lazy1标记01覆盖,lazy2标记异或(即取反)。
如果在lazy1标记之前,就已经有lazy2异或标记了,那么我们就可以直接去掉lazy2标记(赋值为0),直接进行置01标记;
如果在lazy2异或标记之前,就有01标记了,那么就需要处理一下,即对lazy1进行异或。 具体还是见代码吧,主要是操作繁琐了点
*/
using namespace std;
const int maxn=;
int t,n,m; struct Node{
int lsum[],rsum[],msum[]; //统计0/1的左连续的个数,右连续的个数,最大的连续个数
int num[]; //统计0/1的个数
int lazy1; //标记01覆盖
int lazy2; //标记取反
int len; //区间长度
}tree[maxn<<]; void pushUp(Node &rt,Node &ls,Node &rs){
rt.lsum[]=ls.lsum[];rt.rsum[]=rs.rsum[];
rt.lsum[]=ls.lsum[];rt.rsum[]=rs.rsum[]; rt.num[]=ls.num[]+rs.num[];
rt.num[]=ls.num[]+rs.num[];
if(ls.lsum[]==ls.len)
rt.lsum[]+=rs.lsum[];
if(rs.rsum[]==rs.len)
rt.rsum[]+=ls.rsum[];
rt.msum[]=ls.rsum[]+rs.lsum[];
rt.msum[]=max(rt.msum[],max(ls.msum[],rs.msum[])); if(ls.lsum[]==ls.len)
rt.lsum[]+=rs.lsum[];
if(rs.rsum[]==rs.len)
rt.rsum[]+=ls.rsum[];
rt.msum[]=ls.rsum[]+rs.lsum[];
rt.msum[]=max(rt.msum[],max(ls.msum[],rs.msum[]));
}
void changexor(Node &rt){
if(rt.lazy1!=-)
rt.lazy1^=; //如果之前有01标记,那么就对01标记异或一下即可
else
rt.lazy2^=; //否则对取反标记异或
swap(rt.num[],rt.num[]);
swap(rt.lsum[],rt.lsum[]);
swap(rt.rsum[],rt.rsum[]);
swap(rt.msum[],rt.msum[]);
} void pushDown(Node &rt,Node &ls,Node &rs,int m){
/*
因为lazy1和lazy2标记只能同时存在一个,所以只需对其中一个操作即可
如果现有标记为lazy1,若进行取反,对lazy1异或即可,即原本全部覆盖成0的变成1,原本为1的变成0,不需对lazy2异或;
若进行覆盖操作,那么直接对lazy1修改。
如果现有标记为lazy2,若进行覆盖操作,那么lazy2直接变为0,;若进行取反操作,则对lazy2进行异或
*/
if(rt.lazy1!=-){
//01覆盖区间
ls.lazy1=rs.lazy1=rt.lazy1;
rs.lazy2=ls.lazy2=;
ls.num[rt.lazy1]=ls.lsum[rt.lazy1]=ls.rsum[rt.lazy1]=ls.msum[rt.lazy1]=m-m/;
ls.num[!rt.lazy1]=ls.lsum[!rt.lazy1]=ls.rsum[!rt.lazy1]=ls.msum[!rt.lazy1]=;
rs.num[rt.lazy1]=rs.lsum[rt.lazy1]=rs.rsum[rt.lazy1]=rs.msum[rt.lazy1]=m/;
rs.num[!rt.lazy1]=rs.lsum[!rt.lazy1]=rs.rsum[!rt.lazy1]=rs.msum[!rt.lazy1]=;
rt.lazy1=-;
}
else if(rt.lazy2){
//对区间取反
rt.lazy2=;
changexor(ls);
changexor(rs);
}
}
void build(int rt,int L,int R){
tree[rt].len=R-L+;
tree[rt].lazy1=-; //build时都忘记初始化了啊
tree[rt].lazy2=; //build时都忘记初始化了啊
if(L==R){
int v;
scanf("%d",&v);
tree[rt].lsum[v]=tree[rt].rsum[v]=tree[rt].msum[v]=;
tree[rt].lsum[!v]=tree[rt].rsum[!v]=tree[rt].msum[!v]=;
tree[rt].num[v]=;
tree[rt].num[!v]=;
tree[rt].lazy1=-;
return;
}
int mid=(L+R)>>;
build(lson);
build(rson);
pushUp(tree[rt],tree[rt<<],tree[rt<<|]);
} //进行操作01覆盖区间
void update(int rt,int L,int R,int l,int r,int c){
if(l<=L&&R<=r){
tree[rt].lazy2=; //之前的取反操作就无效了
tree[rt].num[c]=tree[rt].lsum[c]=tree[rt].rsum[c]=tree[rt].msum[c]=(R-L+);
tree[rt].num[!c]=tree[rt].lsum[!c]=tree[rt].rsum[!c]=tree[rt].msum[!c]=;
tree[rt].lazy1=c;
return;
}
pushDown(tree[rt],tree[rt<<],tree[rt<<|],R-L+);
int mid=(L+R)>>;
if(l<=mid)
update(lson,l,r,c);
if(r>mid)
update(rson,l,r,c);
pushUp(tree[rt],tree[rt<<],tree[rt<<|]);
}
//进行取反操作
void updatexor(int rt,int L,int R,int l,int r){
if(l<=L&&R<=r){
if(tree[rt].lazy1!=-)
tree[rt].lazy1^=; //如果之前有01标记,则要进行处理,对其异或,即取反
else
tree[rt].lazy2^=;
//只要将值互换一下即可
swap(tree[rt].num[],tree[rt].num[]);
swap(tree[rt].lsum[],tree[rt].lsum[]);
swap(tree[rt].rsum[],tree[rt].rsum[]);
swap(tree[rt].msum[],tree[rt].msum[]);
return;
}
pushDown(tree[rt],tree[rt<<],tree[rt<<|],R-L+);
int mid=(L+R)>>;
if(l<=mid)
updatexor(lson,l,r);
if(r>mid)
updatexor(rson,l,r);
pushUp(tree[rt],tree[rt<<],tree[rt<<|]);
}
//查询时,类型设为Node,进行节点合并,这样就方便好多
Node query(int rt,int L,int R,int l,int r){
if(l<=L&&R<=r){
return tree[rt];
}
pushDown(tree[rt],tree[rt<<],tree[rt<<|],R-L+);
int mid=(L+R)>>;
Node tmp,r1,r2;
if(r<=mid)
tmp=query(lson,l,r);
else if(l>mid)
tmp=query(rson,l,r);
else{
r1=query(lson,l,mid);
r2=query(rson,mid+,r);
tmp.len=r1.len+r2.len;
pushUp(tmp,r1,r2); //将节点r1和r2合并成tmp
}
return tmp;
} int main()
{
int op,a,b;
Node ans;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
build(,,n);
for(int i=;i<=m;i++){
scanf("%d%d%d",&op,&a,&b);
a++;b++;
if(op<=)
update(,,n,a,b,op);
else if(op==)
updatexor(,,n,a,b);
else{
ans=query(,,n,a,b);
if(op==)
printf("%d\n",ans.num[]);
else
printf("%d\n",ans.msum[]);
}
}
}
return ;
}

HDU 3397 Sequence operation (区间合并,操作比较多)的更多相关文章

  1. 【线段树】HDU 3397 Sequence operation 区间合并

    操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters i ...

  2. 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变 ...

  3. HDU 3397 Sequence operation(区间合并 + 区间更新)

    题目链接:pid=3397">http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给定n个数,由0,1构成.共同拥有5种操作. 每一个操 ...

  4. 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 ...

  5. hdu 3397 Sequence operation(很有意思的线段树题)

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  6. HDU 3397 Sequence operation

    题目:下列操作 Change operations:0 a b change all characters into '0's in [a , b]1 a b change all character ...

  7. hdu 3397 Sequence operation (线段树 区间合并 多重标记)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意: 给你一串01串,有5种操作 0. 区间全部变为0 1.区间全部变为1 2.区间异或 3.询问 ...

  8. (简单) HDU 3397 Sequence operation,线段树+区间合并。

    Problem Description lxhgww got a sequence contains n characters which are all '0's or '1's. We have ...

  9. hdu 3397 Sequence operation(线段树:区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给你一个长度为n的0,1序列,支持下列五种操作, 操作0(0 a b):将a到b这个区间的 ...

随机推荐

  1. 配置PostgreSQL Streaming Replication集群

    运行环境: Primary: 192.168.0.11 Standby: 192.168.0.21, 192.168.0.22 OS: CentOS 6.2 PostgreSQL: 9.1.2 版本以 ...

  2. js设计模式(9)---代理模式

    0.前言 KG.PP被交易到了布鲁克林篮网,我的心情很复杂,一方面为他们不能终老celtics感到惋惜,另一方面为他们能够再次冲击总冠军感到高兴.从07年以来,作为一个铁杆celtics球迷,他们给我 ...

  3. 【Qt】Qt国际化(系统文本-QMessageBox按钮、QLineEdit右键菜单等)【转】

    简介 使用Qt的时候,经常会遇到英文问题,例如:QMessageBox中的按钮.QLineEdit.QSpinBox.QScrollBar中的右键菜单等.通常情况下,我们软件都不会是纯英文的,那么如何 ...

  4. Silverlight动画的基本知识、关键帧动画

    基础知识 (一)动画:是快速播放一系列图像(其中每个图像与下一个图像略微不同)给人造成的一种幻觉 (二)动画类型:两类    (1)From/To/By动画:在起始值和结束值之间进行动画处理.     ...

  5. online learning

    转自http://blog.csdn.net/sjkldjflakj/article/details/51886277 不同于以往的批量学习,即给了许多的已标记好的资料来学习出一个假设函数,onlin ...

  6. 利用python2.7正则表达式进行豆瓣电影Top250的网络数据采集及MySQL数据库操作

    转载请注明出处 利用python2.7正则表达式进行豆瓣电影Top250的网络数据采集 1.任务 采集豆瓣电影名称.链接.评分.导演.演员.年份.国家.评论人数.简评等信息 将以上数据存入MySQL数 ...

  7. CentOS 6.3 配置 yum

    ContOS 配置yum:1.cd /etc/yum.repos.d2.创建个任意目录,将所有文件移动到创建的目录中,除了CentOS-Media.repo3.编辑CentOS-Media.repov ...

  8. virtualbox usb连接问题解决

    生命在于折腾... 神奇的liinux... ubuntu 14.04 LTS sudo apt-get install virtualbox -y 然后建好虚拟机之后(windows也好,linux ...

  9. redhat或centos关闭防火墙并开启sshd服务

    使用putty连接虚拟机的redhat连不上时处理方案: 这里使用的是VMware Workstation,  将宿主机与虚拟机之间的网络使用 ‘桥接方式’: 1.关闭宿主机与虚拟机的防火墙, 在re ...

  10. Daily Scrum 11.11

    摘要:本次会议继续讨论程序的问题以及单元测试和集成测试,本次测试为1.02版本.本次的Task列表如下: Task列表 出席人员 Today's Task Tomorrow's Task 刘昊岩  t ...