题意:

 0 a b 把 [a, b] 区间内的所有数全变成0

 1 a b 把 [a, b] 区间内的所有数全变成1

 2 a b 把 [a,b] 区间内的所有数全部取反

 3 a b 询问 [a, b] 区间内总共有多少个1

 4 a b 询问 [a, b] 区间内最多有多少个连续的1

 思路:

首先 线段树 可以搞个标记 flag 是否都是 1(flag=1)/0(flag=-1) LAZY一下

询问区间有多少个 1 ,那就是求和而已?

询问区间最多有多少个连续的1 ?

主要是区间合并的时候要判断

左儿子的Right_Num ==1 && 右儿子的Left_Num ==1 然后还要算下这段区间,和最大值比较。

so,我再搞两个值,一个结点区间的 左端点 连续为 1 的距离,右端点 连续为1 的距离

后面发现还要再添,一个结点区间的 左端点 连续为 0 的距离,右端点 连续为0 的距离,方便反转

现在发现,线段树 就是个 大模拟= =、好像所有的东西都是大模拟。。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL; const int N=1e5+10; struct Seg{
int Left,Right;
int Flag; //标记
int Sum; //区间1的个数
int Max_Len; //区间 连续 1的 最长长度
int Left_Len1,Right_Len1; //区间左端点连续为1的距离,右端点 连续为1 的距离
int Left_Len0,Right_Len0; //区间左端点连续为0的距离,右端点 连续为0 的距离
}q[N*4]; void Pushdown(int num)
{
if(!q[num].Flag) return;
if(q[num].Flag==1)
{
q[num<<1].Sum=q[num<<1].Left_Len1=q[num<<1].Right_Len1=q[num<<1].Max_Len=(q[num<<1].Right-q[num<<1].Left+1);
q[num<<1].Left_Len0=q[num<<1].Right_Len0=0;
q[num<<1].Flag=1; q[num<<1|1].Sum=q[num<<1|1].Left_Len1=q[num<<1|1].Right_Len1=q[num<<1|1].Max_Len=(q[num<<1|1].Right-q[num<<1|1].Left+1);
q[num<<1|1].Left_Len0=q[num<<1|1].Right_Len0=0;
q[num<<1|1].Flag=1; q[num].Flag=0;
}
else
{
q[num<<1].Sum=q[num<<1].Left_Len1=q[num<<1].Right_Len1=q[num<<1].Max_Len=0;
q[num<<1].Left_Len0=q[num<<1].Right_Len0=(q[num<<1].Right-q[num<<1].Left+1);
q[num<<1].Flag=-1; q[num<<1|1].Sum=q[num<<1|1].Left_Len1=q[num<<1|1].Right_Len1=q[num<<1|1].Max_Len=0;
q[num<<1|1].Left_Len0=q[num<<1|1].Right_Len0=(q[num<<1|1].Right-q[num<<1|1].Left+1);
q[num<<1|1].Flag=-1; q[num].Flag=0;
}
} void Pushup(int num)
{
if(q[num].Sum==(q[num].Right-q[num].Left+1))
{
q[num].Flag=1;
q[num].Left_Len1=q[num].Right_Len1=q[num].Max_Len=q[num].Sum;
q[num].Left_Len0=q[num].Right_Len0=0;
}
else if(!q[num].Sum)
{
q[num].Flag=-1;
q[num].Left_Len1=q[num].Right_Len1=q[num].Max_Len=q[num].Sum;
q[num].Left_Len0=q[num].Right_Len0=q[num].Right-q[num].Left+1;
}
else
{
q[num].Flag=0; int Max=max(q[num<<1].Max_Len,q[num<<1|1].Max_Len);
Max=max(q[num<<1].Right_Len1+q[num<<1|1].Left_Len1,Max);
q[num].Max_Len=Max; if(q[num<<1].Left_Len1==(q[num<<1].Right-q[num<<1].Left+1))
{
q[num].Left_Len1=q[num<<1].Left_Len1+q[num<<1|1].Left_Len1;
q[num].Left_Len0=0;
}
else
{
q[num].Left_Len1=q[num<<1].Left_Len1; if(q[num<<1].Left_Len0==(q[num<<1].Right-q[num<<1].Left+1))
q[num].Left_Len0=q[num<<1].Left_Len0+q[num<<1|1].Left_Len0;
else
q[num].Left_Len0=q[num<<1].Left_Len0;
} if(q[num<<1|1].Right_Len1==(q[num<<1|1].Right-q[num<<1|1].Left+1))
{
q[num].Right_Len1=q[num<<1].Right_Len1+q[num<<1|1].Right_Len1;
q[num].Right_Len0=0;
}
else
{
q[num].Right_Len1=q[num<<1|1].Right_Len1;
if(q[num<<1|1].Right_Len0==(q[num<<1|1].Right-q[num<<1|1].Left+1))
q[num].Right_Len0=q[num<<1].Right_Len0+q[num<<1|1].Right_Len0;
else
q[num].Right_Len0=q[num<<1|1].Right_Len0;
}
}
} void Build(int num,int Left,int Right)
{
q[num].Left=Left;q[num].Right=Right;
if(Left==Right)
{
scanf("%d",&q[num].Sum);
if(q[num].Sum==1) q[num].Flag=1;
else q[num].Flag=-1;
q[num].Left_Len1=q[num].Right_Len1=q[num].Max_Len=q[num].Sum;
q[num].Left_Len0=q[num].Right_Len0=1-q[num].Sum;
return;
}
int Mid=(q[num].Left+q[num].Right)>>1;
Build(num<<1,Left,Mid);
Build(num<<1|1,Mid+1,Right); q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
Pushup(num);
} void Update1(int num,int Left,int Right)
{
if(q[num].Left>=Left && q[num].Right<=Right)
{
q[num].Flag=-1;
q[num].Left_Len1=q[num].Right_Len1=q[num].Max_Len=q[num].Sum=0;
q[num].Left_Len0=q[num].Right_Len0=q[num].Right-q[num].Left+1;
return;
}
Pushdown(num); int Mid=(q[num].Left+q[num].Right)>>1;
if(Mid>=Right) Update1(num<<1,Left,Right);
else if(Mid<Left) Update1(num<<1|1,Left,Right);
else
{
Update1(num<<1,Left,Mid);
Update1(num<<1|1,Mid+1,Right);
} q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
Pushup(num);
} void Update2(int num,int Left,int Right)
{
if(q[num].Left>=Left && q[num].Right<=Right)
{
q[num].Flag=1;
q[num].Left_Len1=q[num].Right_Len1=q[num].Max_Len=q[num].Sum=(q[num].Right-q[num].Left+1);
q[num].Left_Len0=q[num].Right_Len0=0;
return;
} Pushdown(num); int Mid=(q[num].Left+q[num].Right)>>1;
if(Mid>=Right) Update2(num<<1,Left,Right);
else if(Mid<Left) Update2(num<<1|1,Left,Right);
else
{
Update2(num<<1,Left,Mid);
Update2(num<<1|1,Mid+1,Right);
} q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
Pushup(num);
} void Update3(int num,int Left,int Right)
{
if(q[num].Left>=Left && q[num].Right<=Right && (q[num].Sum==0||q[num].Sum==(q[num].Right-q[num].Left+1)))
{
if(q[num].Sum==(q[num].Right-q[num].Left+1)) q[num].Flag=-1;
else q[num].Flag=1;
q[num].Max_Len=q[num].Sum=q[num].Right-q[num].Left+1-q[num].Sum;
swap(q[num].Right_Len0,q[num].Right_Len1);
swap(q[num].Left_Len0,q[num].Left_Len1);
return;
} Pushdown(num); int Mid=(q[num].Left+q[num].Right)>>1;
if(Mid>=Right) Update3(num<<1,Left,Right);
else if(Mid<Left) Update3(num<<1|1,Left,Right);
else
{
Update3(num<<1,Left,Mid);
Update3(num<<1|1,Mid+1,Right);
} q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
Pushup(num);
} int Query(int num,int Left,int Right)
{
if(q[num].Left>=Left && q[num].Right<=Right)
return q[num].Sum;
Pushdown(num);
int Mid=(q[num].Left+q[num].Right)>>1;
if(Mid>=Right)
return Query(num<<1,Left,Right);
else if(Mid<Left)
return Query(num<<1|1,Left,Right);
else
return Query(num<<1,Left,Mid)+Query(num<<1|1,Mid+1,Right);
} int MaxLen(int num,int Left,int Right)
{
if(q[num].Left>=Left && q[num].Right<=Right) return q[num].Max_Len;
Pushdown(num);
int Mid=(q[num].Left+q[num].Right)>>1;
if(Mid>=Right) return MaxLen(num<<1,Left,Right);
else if(Mid<Left) return MaxLen(num<<1|1,Left,Right);
else
{
int Len1=MaxLen(num<<1,Left,Mid);
int Len2=MaxLen(num<<1|1,Mid+1,Right);
int Len3=min(q[num<<1].Right_Len1,Mid-Left+1) + min(q[num<<1|1].Left_Len1,Right-Mid);
return max(Len1,max(Len2,Len3));
}
} int main()
{
int n,m,x;
int Left,Right;
scanf("%d%d",&n,&m);
Build(1,1,n); while(m--){
scanf("%d%d%d",&x,&Left,&Right);
Left++;Right++;
switch(x)
{
case 0: { Update1(1,Left,Right); break;}
case 1: { Update2(1,Left,Right); break;}
case 2: { Update3(1,Left,Right); break;}
case 3: { printf("%d\n",Query(1,Left,Right)); break;}
case 4: { printf("%d\n",MaxLen(1,Left,Right)); break;}
}
}
return 0;
}

BZOJ 1858【线段树】的更多相关文章

  1. BZOJ 1858 线段树

    标记会重叠需要判断. #include <bits/stdc++.h> using namespace std; inline int Max(int x,int y) {return x ...

  2. BZOJ 1798 (线段树||分块)的标记合并

    我原来准备做方差的.. 结果发现不会维护两个标记.. 就是操作变成一个 a*x+b ,每次维护a , b 即可 加的时候a=1 ,b=v 乘的时候a=v ,b=0 #include <cstdi ...

  3. HYSBZ 1858 线段树 区间合并

    //Accepted 14560 KB 1532 ms //线段树 区间合并 /* 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[ ...

  4. bzoj 3999 线段树区间提取 有序链剖

    看错题目了,想成每个城市都可以买一个东西,然后在后面的某个城市卖掉,问最大收益.这个可以类似维护上升序列的方法在O(nlog^3n)的时间复杂度内搞定 这道题用到的一些方法: 1. 可以将有关的线段提 ...

  5. bzoj 3211 线段树

    开方操作最多进行5次就可以把出现的任何数变成1. 所以用线段树暴力修改,以后修改时只需看一下是否当前区间都是0或1,如果是那么就直接返回. /***************************** ...

  6. bzoj 1018 线段树维护连通性

    本题将一道LCT的题特殊化(支持加边和删边,询问图的连通性),将图变成了2×m的网格图,然后就神奇地可以用线段树来维护. 对于每个区间[l,r],维护其四个角落之间的连通性(仅仅通过[l,r]这段的边 ...

  7. bzoj 3212 线段树

    裸的线段树 /************************************************************** Problem: User: BLADEVIL Langua ...

  8. bzoj 2120 线段树套平衡树

    先吐下槽,改了快一个小时,最后发现是SBT的delete写错了,顿时就有想死的心..... 首先对于这道题,我们应该先做一下他的小问题,bzoj1878,虽然和这道题几乎一点关系没有, 但是能给我们一 ...

  9. bzoj 1901 线段树套平衡树+二分答案查询

    我们就建一颗线段树,线段树的每一个节点都是一颗平衡树,对于每个询问来说,我们就二分答案, 查询每个二分到的mid在这个区间里的rank,然后就行了 /************************* ...

  10. BZOJ 1012 线段树||单调队列

    非常裸的线段树  || 单调队列: 假设一个节点在队列中既没有时间优势(早点入队)也没有值优势(值更大),那么显然不管在如何的情况下都不会被选为最大值. 既然它仅仅在末尾选.那么自然能够满足以上的条件 ...

随机推荐

  1. java反射(二)

    java的很多框架都是基于反射的.

  2. 分享知识-快乐自己:slor 服务的搭建

    Slor 服务的搭建: 1):上传 solr  tar包到指定目录 2):解压到 指定目录下 [root@admin tools]# tar -zxvf solr-4.10.3.tgz.tgz -C ...

  3. PL/SQL学习笔记_01_基础:变量、流程控制

    PL/SQL语句可以在Oracle客户端的 SQL窗口或者 command  窗口中运行 在SQL窗口中运行步骤同 SQL语句 在command  窗口中运行的步骤如下: 1)File—new com ...

  4. BEC listen and translation exercise 39

    What about jigsaw puzzle design for visually handicapped?给视觉障碍人士设计拼图怎么样? Length is 50cm, and then th ...

  5. codeforces 598E E. Chocolate Bar(区间dp)

    题目链接: E. Chocolate Bar time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  6. Convolutional Neural Networks for Visual Recognition 4

    Modeling one neuron 下面我们开始介绍神经网络,我们先从最简单的一个神经元的情况开始,一个简单的神经元包括输入,激励函数以及输出.如下图所示: 一个神经元类似一个线性分类器,如果激励 ...

  7. POJ2891Strange Way to Express Integers (线性同余方程组)

    Elina is reading a book written by Rujia Liu, which introduces a strange way to express non-negative ...

  8. Centos6.5上的iptables

    1.Centos6.5默认开启了iptables 当Centos6.5上安装了MySQL后,在远程连接它,如果出现10060的错误,说明iptables在起作用. 关闭iptables即可,sudo ...

  9. Python:模块详解及import本质

    转于:http://www.cnblogs.com/itfat/p/7481972.html 博主:东大网管 一.定义: 模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能), ...

  10. 关于audio.js的研究

    ——杂言:audio.js结合使用html5的audio组件实现了音频的原位播放功能.虽然项目里已经使用一段时间了,不过我是最近才开始有所接触,惭愧.个人见解若有不对,请帮忙纠正,谢谢. 官方相关链接 ...