题目大意

对一个只有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. E. Xenia and Tree 分块 + LCA

    http://codeforces.com/contest/342/problem/E 如果把询问1存起来,每到sqrt(m)的时候再处理一次. 那么总复杂度就是msqrt(m)的. 把要变颜色的节点 ...

  2. 基于webmagic的爬虫小应用

    以前没有写过爬虫程序,最近两天就研究了一下java的爬虫框架webmagic.然后写了一个demo 写爬虫的基本思想: 1.抓取目标连接 2.根据页面中标签,抓捕你需要的内容 3.保存结果集 以下是实 ...

  3. 动手实现 Redux(三):纯函数(Pure Function)简介

    我们接下来会继续优化我们的 createStore 的模式,让它使我们的应用程序获得更好的性能. 但在开始之前,我们先用一节的课程来介绍一下一个函数式编程里面非常重要的概念 —— 纯函数(Pure F ...

  4. AJPFX关于学习java遇到的问题:对算法和数据结构不熟悉

    为什么我先拿“数据结构和算法”说事捏?这玩意是写程序最最基本的东东.不管你使用 Java 还是其它的什么语言,都离不开它.而且这玩意是跨语言的,学好之后不管在哪门语言中都能用得上. 既然“数据结构和算 ...

  5. 命令模式和php实现

    命令模式: 命令模式(Command Pattern):将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及支持可撤销的操作.命令模式是一种对象行为型模 ...

  6. JDK NIO SelectionKey bug

    此bug项目中使用elasticSearch中出现的,原因是,nio事件选择器,在特性内核下以及jdk6版本中,出现不hold线程,死循环获取事件的bug,导致cup使用率过高: 此bug在官网已被修 ...

  7. java中properties的使用实例

    package com.ywx.io; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputSt ...

  8. MongoDB最简单的入门教程之三 使用Java代码往MongoDB里插入数据

    前两篇教程我们介绍了如何搭建MongoDB的本地环境: MongoDB最简单的入门教程之一 环境搭建 以及如何用nodejs读取MongoDB里的记录: MongoDB最简单的入门教程之二 使用nod ...

  9. mybatis中存储过程的调用

    dao层 // 调用存储过程 void callProcedureGrantEarnings(@Param("params") Map<String,Object> p ...

  10. uva1628 Pizza Delivery

    fixing great wall 的变形dp(i,j,k,p)不考虑i-j的客人,还要送k个人,目前位置在p起点i和总数量k都要枚举dp(i,j,k,p)=max(dp(m,j,k-1,p)+val ...