这个是去年遗留历史问题,之前思路混乱,搞了好多发都是WA,就没做了

自从上次做了大白书上那个双重懒惰标记的题目,做这个就思路很清晰了

跟上次大白上那个差不多,这个也是有一个sets标记,代表这个区间全部置为0或者1,没有置位的时候为-1

还有个rev标记,代表翻转操作,0代表当前不翻,1代表当前翻

要注意一下优先级,发现有不同的弄法,我是这个弄得,有set操作的时候,set标记设值,并把当前节点的rev标记设为0,因为不管要不要rev,当前set操作肯定直接覆盖了

rev操作不改变set操作,在pushdown的时候,先考虑set标记再弄rev标记,这也是很好理解的,因为一旦rev和set共存,肯定是rev在set后面。

有几个细节要注意一下,一开始行云流水一气呵成,发现还是WA了,就是这几个地方,

1.除了set的时候强制给rev弄成0,其他任何时候对rev标记操作都是^1,取反,这个也很好理解,之前在pushdown里面我就是直接传值,肯定不对嘛

2.在pushdown里面的set下传操作也要记得把子树的rev标记抹除,一开始只在主修改函数里写了,这里没写,WA的不明不白,理由跟上面的一样

然后就基本上没问题了

#include <iostream>
#include <cstdio>
#include <cstring>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
const int N=100000+10;
int d[N*3],maxc[N*3],lc[N*3],rc[N*3],maxc0[N*3],lc0[N*3],rc0[N*3];
int sets[N*3],rev[N*3];
int n,Q;
int A[N];
void up(int rt,int l,int r)
{
int mid=(l+r)>>1;
d[rt]=d[rt<<1]+d[rt<<1|1];
maxc[rt]=max(maxc[rt<<1],maxc[rt<<1|1]);
maxc[rt]=max(maxc[rt],lc[rt<<1|1]+rc[rt<<1]);
lc[rt]=lc[rt<<1];
rc[rt]=rc[rt<<1|1];
if (lc[rt<<1]==mid-l+1) lc[rt]+=lc[rt<<1|1];
if (rc[rt<<1|1]==r-mid) rc[rt]+=rc[rt<<1]; maxc0[rt]=max(maxc0[rt<<1],maxc0[rt<<1|1]);
maxc0[rt]=max(maxc0[rt],lc0[rt<<1|1]+rc0[rt<<1]);
lc0[rt]=lc0[rt<<1];
rc0[rt]=rc0[rt<<1|1];
if (lc0[rt<<1]==mid-l+1) lc0[rt]+=lc0[rt<<1|1];
if (rc0[rt<<1|1]==r-mid) rc0[rt]+=rc0[rt<<1];
}
void build(int rt,int l,int r)
{
sets[rt]=-1;
rev[rt]=0;
if (l>=r){
d[rt]=maxc[rt]=A[l];
lc[rt]=rc[rt]=A[l];
lc0[rt]=rc0[rt]=maxc0[rt]=1-A[l];
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
up(rt,l,r);
}
void pushdown(int rt,int l,int r)
{
if (l>=r) return;
int mid=(l+r)>>1;
if (sets[rt]>=0){
maxc[rt<<1]=lc[rt<<1]=rc[rt<<1]=d[rt<<1]=(mid-l+1)*sets[rt];
maxc[rt<<1|1]=lc[rt<<1|1]=rc[rt<<1|1]=d[rt<<1|1]=(r-mid)*sets[rt]; maxc0[rt<<1]=lc0[rt<<1]=rc0[rt<<1]=(mid-l+1)*(1-sets[rt]);
maxc0[rt<<1|1]=lc0[rt<<1|1]=rc0[rt<<1|1]=(r-mid)*(1-sets[rt]); sets[rt<<1]=sets[rt<<1|1]=sets[rt];
rev[rt<<1]=rev[rt<<1|1]=0;
sets[rt]=-1; }
if (rev[rt]>0){
d[rt<<1]=(mid-l+1)-d[rt<<1];
d[rt<<1|1]=(r-mid)-d[rt<<1|1]; int t1,t2,t3;
t1=maxc[rt<<1];t2=lc[rt<<1];t3=rc[rt<<1];
maxc[rt<<1]=maxc0[rt<<1];
lc[rt<<1]=lc0[rt<<1];
rc[rt<<1]=rc0[rt<<1];
maxc0[rt<<1]=t1;
lc0[rt<<1]=t2;
rc0[rt<<1]=t3;
t1=maxc[rt<<1|1];t2=lc[rt<<1|1];t3=rc[rt<<1|1];
maxc[rt<<1|1]=maxc0[rt<<1|1];
lc[rt<<1|1]=lc0[rt<<1|1];
rc[rt<<1|1]=rc0[rt<<1|1];
maxc0[rt<<1|1]=t1;
lc0[rt<<1|1]=t2;
rc0[rt<<1|1]=t3;
rev[rt<<1]^=1;
rev[rt<<1|1]^=1;
rev[rt]=0;
}
}
void change(int val,int L,int R,int rt,int l,int r)
{
if (L<=l && r<=R){
d[rt]=(r-l+1)*val;
lc[rt]=rc[rt]=(r-l+1)*val;
maxc[rt]=(r-l+1)*val;
lc0[rt]=rc0[rt]=maxc0[rt]=(r-l+1)*(1-val);
sets[rt]=val;
rev[rt]=0;
return;
}
pushdown(rt,l,r);
int mid=(l+r)>>1;
if (L>mid) change(val,L,R,rson);
else
if (R<=mid) change(val,L,R,lson);
else{
change(val,L,R,rson);
change(val,L,R,lson);
}
up(rt,l,r);
}
void revers(int L,int R,int rt,int l,int r)
{ if (L<=l && r<=R)
{ d[rt]=(r-l+1)-d[rt];
int t1,t2,t3;
t1=maxc[rt];t2=lc[rt];t3=rc[rt];
maxc[rt]=maxc0[rt];lc[rt]=lc0[rt];rc[rt]=rc0[rt];
maxc0[rt]=t1;lc0[rt]=t2;rc0[rt]=t3;
rev[rt]^=1;
return;
}
pushdown(rt,l,r);
int mid=(l+r)>>1;
if (R<=mid) revers(L,R,lson);
else
if (L>mid) revers(L,R,rson);
else
{
revers(L,R,lson);
revers(L,R,rson);
}
up(rt,l,r);
}
int output(int op,int L,int R,int rt,int l,int r)
{
if (L==l && r==R){
if (op==3) return d[rt];
else return maxc[rt];
}
pushdown(rt,l,r);
int mid=(l+r)>>1;
if (L>mid) return output(op,L,R,rson);
else
if (R<=mid) return output(op,L,R,lson);
else
{
int ret1=output(op,L,mid,lson);
int ret2=output(op,mid+1,R,rson);
if (op==3) return ret1+ret2;
else{
int ret=max(ret1,ret2);
int t1=min(rc[rt<<1],mid-L+1);
int t2=min(lc[rt<<1|1],R-mid);
ret=max(ret,t1+t2);
return ret;
}
}
}
int main()
{
int t,op,a,b;
scanf("%d",&t);
while (t--)
{
scanf("%d%d",&n,&Q);
for (int i=1;i<=n;i++) scanf("%d",&A[i]);
build(1,1,n);
while (Q--)
{
scanf("%d%d%d",&op,&a,&b);
a++;b++;
if (op<=1){
change(op,a,b,1,1,n);
}
else
if (op==2){
revers(a,b,1,1,n);
}
else
{
int ans=output(op,a,b,1,1,n);
printf("%d\n",ans);
}
}
}
return 0;
}

  

HDU 3397 线段树 双懒惰标记的更多相关文章

  1. hdu 3397 线段树双标记

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

  2. HDU 4107 Gangster(线段树 特殊懒惰标记)

    两种做法. 第一种:标记区间最大值和最小值,若区间最小值>=P,则本区间+2c,若区间最大值<P,则本区间+c.非常简单的区间更新. 最后发一点牢骚:最后query查一遍就行,我这个2B竟 ...

  3. poj3468 线段树的懒惰标记

    题目链接:poj3468 题意:给定一段数组,有两种操作,一种是给某段区间加c,另一种是查询一段区间的和 思路:暴力的方法是每次都给这段区间的点加c,查询也遍历一遍区间,复杂度是n*n,肯定过不去,另 ...

  4. POJ 3667 & HDU 3308 & HDU 3397 线段树的区间合并

    看到讲课安排上 线段树有一节课"区间合并" 我是迷茫的 因为并没有见过 然后了解了一下题目 发现以前写过 还是很麻烦的树链剖分 大概是 解决带修改的区间查询"连续问题&q ...

  5. HDU 3954 Level up (线段树特殊懒惰标记)

    http://blog.csdn.net/acm_cxlove/article/details/7548087 感觉最巧的是定义了min_dis……将区间内有无英雄升级分开处理 #include &l ...

  6. hdu 3397 线段树

    题意: Change operations:0 a b change all characters into '0's in [a , b]1 a b change all characters in ...

  7. HDU 3397 线段树区间修改

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

  8. hdu 4578 线段树(标记处理)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others) ...

  9. hdu 3954 线段树 (标记)

    Level up Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

随机推荐

  1. 警示框UIAlertController的使用(看完马上会用!!)

    本文尽量图文并茂,并且提供对应的代码,确保看到这篇文章马上能够上手使用UIAlertController控件.-我要兑现我的务实宣言- 本文构思: 1.出具效果图,通过这种最直接方式了解该控件的展示效 ...

  2. 【剑指Offer面试编程题】题目1366:栈的压入、弹出序列--九度OJ

    题目描述: 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈 ...

  3. natapp 内网穿透服务

    参考文章:https://www.jianshu.com/p/91a321e584b8 参考文章:https://www.jianshu.com/p/c4cb8666c96a 一.什么是内网穿透 通过 ...

  4. Element 表单校验不消失问题

    由于不好的命名习惯,所以我的:rule   :ref   :model命名就是写了改,改了再写. 直到今天出现了这个毛病就是  “表单验证不消失” 比方说这里的  ‘密码不能为空’,在我已经输入了数字 ...

  5. luogu P2762 太空飞行计划问题

    好像是最大权闭合图,也就是最大流最小割啦,找出最大流的路径输出,这题如何建模呢,一样的先设源点和汇点,源点向每个计划连capacity为赞助数的边,每个计划连相应装置capacity为无穷的边,每个装 ...

  6. 「React Native笔记」在React的 setState 中操作数组和对象的多种方法(合集)

    运用在React 中 setState的对象.数组的操作时是不能用类似array.push()等方法,因为push没有返回值,setState后会出现state变成Number,为了方便他人和自己查看 ...

  7. ios 获取当前系统时间

    1. NSDate + NSDateFormatter NSDate *date = [NSDate date]; NSDateFormatter *format = [[NSDateFormatte ...

  8. Paper代写:别让段落结尾拉低你的分数

    为了达到paper写作格式和字数要求,学生往往会在段末做一件事:总结.都不算是一个很长的段落.本来就写不了多少论证的内容,我们还强制加一个总结句,不仅占用了我们论证的篇幅,而且显得多余(段首的主题句已 ...

  9. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:匿名内部类

    interface A{ public void printInfo() ; // } class B implements A{ // 实现接口 public void printInfo(){ S ...

  10. 2.15 学习总结 之 天气预报APP volley(HTTP库)之StringRequest

    一.说在前面   昨天 学习了序列化的相关知识   今天 1.学习 volley(HTTP库)的 StringRequest请求 2.使用序列化完成相关案例 遇到问题 请求到的参数的出现中文乱码问题 ...