题目大意

对一个只有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. java中stringBuilder的用法

    java中stringBuilder的用法 String对象是不可改变的.每次使用 System.String类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间.在需 ...

  2. Hadoop工作流不足(六)

    不多说,直接上干货! 为此,需要第三方框架.如Azkaban或Oozie! Azkaban https://azkaban.github.io/ 具体,见我的博客,Azkaban概念学习系列.http ...

  3. C#中构造函数和析构函数区别

    把对象的初始化工作放在构造函数中,把清除工作放在析构函数中.当对象被创建时,构造函数被自动执行.当对象消亡时,析构函数被自动执行.这样就不用担心忘记对象的初始化和清除工作. 析构函数是由垃圾回收器控制 ...

  4. 【学习笔记】深入理解js原型和闭包(15)——闭包

    前面提到的上下文环境和作用域的知识,除了了解这些知识之外,还是理解闭包的基础. 至于“闭包”这个词的概念的文字描述,确实不好解释,我看过很多遍,但是现在还是记不住. 但是你只需要知道应用的两种情况即可 ...

  5. qt5.8+vs2015使用Qt5WebEngine搭建环境

    转载请注明出处:http://www.cnblogs.com/dachen408/p/7575094.html 1.项目属性,C/C++,所有选项,附加包含目录新增. $(QTDIR)\include ...

  6. 生成hprof文件,用MAT进行分析

    生成hprof文件可以在DDMS选中进程点击窗口左上角的"dump hprof file"按钮来直接生成,也可以通过在程序加代码中来生成 代码2: void generateHpr ...

  7. 洛谷 P1006 传纸条

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...

  8. Codeforces Gym 2015 ACM Arabella Collegiate Programming Contest(二月十日训练赛)

    A(By talker): 题意分析:以a(int) op b(int)形式给出两个整数和操作符, 求两个整数是否存在操作符所给定的关系 ,有则输出true,无则输出false: 思路:由于无时间复杂 ...

  9. 必知干货:Web前端应用十种常用技术你全都知道吗?

    Web前端应用十种常用技术,随着JS与XHTML的应用普及,越来越多的web界面应用技术出现在网站上,比如我们常见的日历控件,搜索下拉框等,这些web界面应用技术大大的丰富了网站的表现形式,本文将为您 ...

  10. python 人脸识别试水(一)

    1.安装python,在这里我的版本是python 3.6 2.安装pycharm,我的版本是pycharm 2017 3.安装pip  pip 版本10 4.安装 numpy    :pip ins ...