题目大意

对一个只有0和1的序列,支持以下几种操作
1.将区间所有的值变成1
2.将区间所有的值变为0
3.将区间的0和1翻转(0变成1 1变成0)
4.求区间中1的个数
5.求区间连续最长的1的个数

http://vjudge.net/problem/viewProblem.action?id=14689

整整一下午。。。简直把自己修改的都要哭了

lazy标记有先后关系,如to[]覆盖后,那么rev[]翻转标记就应该重新赋为0

我们在pushdown中,是对孩子节点进行更新,那么更新的也是孩子节点的lazy标记,to[]覆盖的也是孩子节点的标记,对于还没用过的rev[cur]是不用变的,

这是它父亲传下来的,确保了正确性的

而在update函数中,每次给to[cur]进行了赋值,那么rev[cur]就要重置为0,因为我们这是对当前节点传入的标记,覆盖执行在当前节点上

PS:就是这破玩意改了我一下午的时间

void update(int cur,int x,int y,int s,int t,int op)
{
    int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    if(x>=s&&y<=t){
        if(op==0){
            lc[cur][0]=rc[cur][0]=mc[cur][0]=y-x+1;
            lc[cur][1]=rc[cur][1]=mc[cur][1]=0;
            sum[cur]=0;
            to[cur]=0,rev[cur]=0;
        }
        else if(op==1){
            lc[cur][0]=rc[cur][0]=mc[cur][0]=0;
            lc[cur][1]=rc[cur][1]=mc[cur][1]=y-x+1;
            sum[cur]=y-x+1;
            to[cur]=1,rev[cur]=0;
        }
        else if(op==2){
            swap(lc[cur][0],lc[cur][1]);
            swap(rc[cur][0],rc[cur][1]);
            swap(mc[cur][0],mc[cur][1]);
            sum[cur]=y-x+1-sum[cur];
            rev[cur]^=1;
        }
        return;
    }
    push_down(cur,x,y);
    if(mid>=s) update(L,s,t,op);
    if(mid+1<=t) update(R,s,t,op);
    push_up(cur,x,y);
}

总代码如下:

 #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define L ls,x,mid
#define R rs,mid+1,y
#define N 100010
int to[N<<],rev[N<<],lc[N<<][],rc[N<<][],mc[N<<][],sum[N<<],X[N];
void push_up(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
sum[cur]=sum[ls]+sum[rs];
for(int i=;i<;i++){
lc[cur][i]=lc[ls][i],rc[cur][i]=rc[rs][i];
mc[cur][i]=max(mc[ls][i],mc[rs][i]);
mc[cur][i]=max(mc[cur][i],rc[ls][i]+lc[rs][i]);
if(lc[ls][i]==mid-x+) lc[cur][i]=lc[ls][i]+lc[rs][i];
if(rc[rs][i]==y-mid) rc[cur][i]=rc[ls][i]+rc[rs][i];
}
}
void push_down(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(to[cur]!=-){
to[ls]=to[rs]=to[cur];
rev[ls]=rev[rs]=;
lc[ls][]=rc[ls][]=mc[ls][]=to[cur]?:mid-x+;
lc[ls][]=rc[ls][]=mc[ls][]=to[cur]?mid-x+:;
lc[rs][]=rc[rs][]=mc[rs][]=to[cur]?:y-mid;
lc[rs][]=rc[rs][]=mc[rs][]=to[cur]?y-mid:;
sum[ls]=to[cur]*(mid-x+);
sum[rs]=to[cur]*(y-mid);
to[cur]=-;
}
if(rev[cur]){
rev[ls]^=,rev[rs]^=;
swap(lc[ls][],lc[ls][]);
swap(lc[rs][],lc[rs][]); swap(rc[ls][],rc[ls][]);
swap(rc[rs][],rc[rs][]); swap(mc[ls][],mc[ls][]);
swap(mc[rs][],mc[rs][]); sum[ls]=mid-x+-sum[ls];
sum[rs]=y-mid-sum[rs]; rev[cur]=;
}
}
void build(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
to[cur]=-,rev[cur]=;
if(x==y){
lc[cur][]=rc[cur][]=mc[cur][]=sum[cur]=X[x];
lc[cur][]=rc[cur][]=mc[cur][]=X[x]^;
//printf("%d\n",mc[cur][0]);
return;
}
build(L);
build(R);
push_up(cur,x,y);
}
void update(int cur,int x,int y,int s,int t,int op)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(x>=s&&y<=t){
if(op==){
lc[cur][]=rc[cur][]=mc[cur][]=y-x+;
lc[cur][]=rc[cur][]=mc[cur][]=;
sum[cur]=;
to[cur]=,rev[cur]=;
}
else if(op==){
lc[cur][]=rc[cur][]=mc[cur][]=;
lc[cur][]=rc[cur][]=mc[cur][]=y-x+;
sum[cur]=y-x+;
to[cur]=,rev[cur]=;
}
else if(op==){
swap(lc[cur][],lc[cur][]);
swap(rc[cur][],rc[cur][]);
swap(mc[cur][],mc[cur][]);
sum[cur]=y-x+-sum[cur];
rev[cur]^=;
}
return;
}
push_down(cur,x,y);
if(mid>=s) update(L,s,t,op);
if(mid+<=t) update(R,s,t,op);
push_up(cur,x,y);
}
void query1(int cur,int x,int y,int s,int t,int &ans)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(x>=s&&y<=t){
ans+=sum[cur];
return;
}
push_down(cur,x,y);
if(mid>=s) query1(L,s,t,ans);
if(mid+<=t) query1(R,s,t,ans);
}
int query2(int cur,int x,int y,int s,int t)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(x>=s&&y<=t){
return mc[cur][];
}
push_down(cur,x,y);
int ans=;
if(mid>=s) ans=max(ans,query2(L,s,t));
if(mid+<=t) ans=max(ans,query2(R,s,t));
return max(ans,min(mid-s+,rc[ls][])+min(t-mid,lc[rs][]));
}
int main()
{
int T,n,m,op,a,b;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&X[i]);
build(,,n);
for(int i=;i<m;i++){
scanf("%d%d%d",&op,&a,&b);
if(op==){
int ans=;
query1(,,n,a+,b+,ans);
printf("%d\n",ans);
}
else if(op==){
printf("%d\n",query2(,,n,a+,b+));
}
else update(,,n,a+,b+,op);
}
}
return ;
}

HDU 3397 双lazy标记的问题的更多相关文章

  1. HDU 3911 Black And White (线段树区间合并 + lazy标记)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3911 给你n个数0和1,m个操作: 0操作  输出l到r之间最长的连续1的个数 1操作  将l到r之间 ...

  2. HDU 1698 just a hook - 带有lazy标记的线段树(用结构体实现)

    2017-08-30 18:54:40 writer:pprp 可以跟上一篇博客做个对比, 这种实现不是很好理解,上一篇比较好理解,但是感觉有的地方不够严密 代码如下: /* @theme:segme ...

  3. HDU 1698 Just a Hook 区间更新 lazy标记

    lazy标记 #include <iostream> #include <cstdio> #include <cstring> #include <sstre ...

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

  5. hdu 3397 线段树双标记

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

  6. HDU1698 just a Hook - 带有lazy标记的线段树

    2017-08-30 16:44:33 writer:pprp 上午刚刚复习了一下不带有lazy标记的线段树, 下午开始学带有lazy标记的线段树 这个是我看大佬代码敲的,但是出了很多问题, 这提醒我 ...

  7. HDU 3397 Sequence operation (区间合并,操作比较多)

    费了我一天半的时间,到处debug,后来才发现,主要是建树的时候只在叶子节点对lazy1和lazy2进行初始化了,父节点都没初始化...晕. 具体见代码吧. #include <iostream ...

  8. POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)

    题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每 ...

  9. poj3468 线段树+lazy标记

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 92921   ...

随机推荐

  1. 【前端】模拟微信上传图片(带预览,支持预览gif)

    一.Html <style type="text/css"> #previewDiv{width:50px;height:50px;overflow:hidden;po ...

  2. 关于ES6的Promise的使用深入理解

    ES6的promise对象研究 什么叫promise? Promise对象可以理解为一次执行的异步操作,使用promise对象之后可以使用一种链式调用的方式来组织代码:让代码更加的直观. 那我们为什么 ...

  3. Git使用简析

    推送本地操作 初始化一个本地Git仓库,在需要添加版本控制的文件夹根目录中使用git init命令. 添加文件到本地Git仓库: git add 文件名 # 添加文件到暂存区 git add . # ...

  4. Mybatis的Service循环调用错误

    org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'z ...

  5. HDU 4465 Candy (数学期望)

    题意:有两个盒子各有n个糖(n<=2*105),每天随机选1个(概率分别为p,1-p),然后吃掉一颗糖.直到有一天打开盒子一看,这个盒子没有糖了.输入n,p,求此时另一个盒子里糖的个数的数学期望 ...

  6. uva 1451 数形结合

    思路:枚举点t,寻找满足条件的点t': 计sum[i]为前i项合,平均值即为sum[t]-sum[t'-1]/t-t'+1 设(Pi=(i,Si),表示点在s中的位置,那么就可以画出坐标图,问题就转化 ...

  7. window Chrome 下允许跨域访问服务端接口设置

    关闭chrome,使用cmd命令进入chrome安装目录cd C:\Program Files (x86)\Google\Chrome\Application 然后使用命令打开chromechrome ...

  8. Zend studio 修改编码格式

    一.临时修改编码格式 edit -> Set Encoding... -> Other(选择) 二.修改软件默认编码格式

  9. QT+lambda 表达式

    #include "mainwidget.h" #include <QPushButton> #include <QDebug> MainWidget::M ...

  10. consul无client模式

    1.推consul的镜像到生产应用全部服务器. 每个consul的server模式的容器,都需要单独的物理服务器. 主节点:docker run -d --net=host --name=consul ...