费了我一天半的时间,到处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. 设置textview背景色为透明

    UITextView *textView=[[UITextView alloc]initWithFrame:CGRectMake(20, 40, 150, 170)];//初始化并设置大小 textV ...

  2. 从零开始搭建TestCpp工程

    目标: 创建一个测试工程,测试工程以列表的方式展示,没一个列表项对应一个场景 1. 创建cocos2d-x工程       现在采用脚本的方式来创建,好处是一次可以创建N个项目的工程.      首先 ...

  3. ASP.NET MVC局部验证及相关问题

    在上一篇“asp.net mvc常用的数据注解和验证以及entity framework数据映射”话题中,有的博友提到 ‘“同一个实体在3-4个地方会发生修改,每个修改需要验证的方式都不一样,后端就不 ...

  4. centos问题集锦

    一. 为什么新装的centos系统无法使用xshell,putty等工具连接? 原因:sshd服务没有启动. 解决: 1)使用命令rpm -qa | grep ssh查看是否已经安装了ssh 2)使用 ...

  5. RouterOS的MikroTik脚本从DNS更新IPSEC端的IP地址

    #Script for changing IPSEC address when DNS changes. #Script will iterate through all peers looking ...

  6. LoadRunner报26612错误的解决方案

    LoadRunner压力测试时,一直会报12261错误,错误内容大概如下: Error -26612: HTTP Status-Code=500 (Internal Server Error) for ...

  7. SSL handshake failed: SSL 错误:在证书中检测到违规的密钥用法。

    问题:在WINDOWS中创建的SVN Server,在Linux client中无法连接.原因:WINDOWS中的证书无法被Linux正确识别,因此需要修改证书,以使双方都可以正确识别. 修改方法如下 ...

  8. 《零成本实现Web自动化测试--基于Selenium》第一章 自动化测试基础

    第一篇 Selenium 和WebDriver工具篇 第一章 自动化测试基础 1.1    初识自动化测试 自动化测试有两种常见方式 1.1.1 代码驱动测试,又叫测试驱动开发(TDD) 1.1.2 ...

  9. 1105. Spiral Matrix (25)

    This time your job is to fill a sequence of N positive integers into a spiral matrix in non-increasi ...

  10. POJ 1195 2维线段树(树套树实现) 树状数组

    1: #include <stdio.h> 2: #include <string.h> 3: #include <stdlib.h> 4: #include &l ...