区间翻转的裸题,wrong了两发,没找bug,直接又打了一遍,这么大量的代码找bug是疯了。

重新开始做线段树的一些题了,感觉对于pushdown与lazy数组有点印象了。

首先,lazy数组是记录的当前数组的改变,不管是这个题的异或,还是加减,lazy数组就是线段树的主要优化原因,当你用的时候你再下放,大大减少了复杂度。但是记录的时候lazy[i]=1时候,tree[i]是要先处理的,然后每次每一查找的时候是先看该节点成不成立,不成立的话,再下放lazy。还有就是update的时候也要下放lazy.

就是这样,这道题的话主要的问题就是区间反转,lazy[i]变换两次的话就是不变,所以用异或来处理刚刚好,区间连续最长的问题就是个模板,记录左最长,右最长,总体最长。

1.在pushup的时候,要注意如果左儿子的左最长已经占了左边的总长,那么父亲节点的左最长就还要加上右儿子的左最长。

父节点的右最长也是相同的

tree[i].wl=tree[lson].wl+((tree[lson].wl==mid-l+1)?tree[rson].wl:0);

2.第二个问题就是在query的时候,找的是左儿子的总体最长,右儿子总体最长,以及左儿子的右最长+右儿子的左最长在询问左端点ql,询问右端点qr之间的总长度。

 return max3(query(Lson,ql,mid),query(Rson,mid+1,qr),min(mid-ql+1,tree[lson].br)+min(qr-mid,tree[rson].bl));

结合全部代码,用宏定义,写起来会快很多还简

洁,但是可能会慢一点,理解理解。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#define myself i,l,r
#define lson i<<1//左儿子
#define rson i<<1|1//右儿子
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define inff 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define me(a,b) memset(a,b,sizeof(a))
#define min4(a,b,c,d) min(min(a,b),min(c,d))
#define min3(x,y,z) min(min(x,y),min(y,z))
#define max4(a,b,c,d) max(max(a,b),max(c,d))
#define max3(x,y,z) max(max(x,y),max(y,z))
typedef long long ll;
using namespace std;
const int maxn=1e5+5;
struct node
{int wl,wr,wm,bl,br,bm;//w表示白的左,右,总;b就是black黑左右总
}tree[maxn<<2];
int lazy[maxn<<2];
int n,m;
void pushup(int i,int l,int r)//往上更新
{int mid=half;tree[i].wl=tree[lson].wl+((tree[lson].wl==mid-l+1)?tree[rson].wl:0);tree[i].bl=tree[lson].bl+((tree[lson].bl==mid-l+1)?tree[rson].bl:0);tree[i].wr=tree[rson].wr+((tree[rson].wr==r-mid)?tree[lson].wr:0);tree[i].br=tree[rson].br+((tree[rson].br==r-mid)?tree[lson].br:0);tree[i].wm=max3(tree[lson].wm,tree[rson].wm,tree[lson].wr+tree[rson].wl);tree[i].bm=max3(tree[lson].bm,tree[rson].bm,tree[lson].br+tree[rson].bl);
}
void change(int x)
{swap(tree[x].wl,tree[x].bl);swap(tree[x].wr,tree[x].br);swap(tree[x].wm,tree[x].bm);
}
void pushdown(int i,int l,int r)
{if(lazy[i]){lazy[lson]^=1;lazy[rson]^=1;change(lson);change(rson);lazy[i]=0;return;}
}
void update(int i,int l,int r,int ql,int qr)
{if(ql<=l&&qr>=r){change(i);lazy[i]^=1;return ;}int mid=half;pushdown(myself);if(qr<=mid) update(Lson,ql,qr);else if(ql>mid) update(Rson,ql,qr);else{update(Lson,ql,mid);update(Rson,mid+1,qr);}pushup(myself);
}
int query(int i,int l,int r,int ql,int qr)
{if(ql<=l&&qr>=r)return tree[i].bm;pushdown(myself);int mid=half;if(qr<=mid) return query(Lson,ql,qr);else if(ql>mid) return query(Rson,ql,qr);else return max3(query(Lson,ql,mid),query(Rson,mid+1,qr),min(mid-ql+1,tree[lson].br)+min(qr-mid,tree[rson].bl));
}
void build(int i,int l,int r)
{int x;lazy[i]=0;if(l==r){scanf("%d",&x);tree[i].bl=tree[i].br=tree[i].bm=x;tree[i].wl=tree[i].wr=tree[i].wm=x^1;return;}int mid=half;build(Lson);build(Rson);pushup(myself);
}
int main()
{int num,x,y;while(scanf("%d",&n)!=EOF){build(1,1,n);scanf("%d",&m);while(m--){scanf("%d%d%d",&num,&x,&y);if(num==0)printf("%d\n",query(1,1,n,x,y));elseupdate(1,1,n,x,y);}}return 0;
}

HDU - 3911 Black And White 区间翻转+区间连续最长相关推荐

  1. 【线段树_区间合并_异或翻转】HDU 3911 Black And White

    HDU 3911 Black And White 题意:有一个只有0和1组成的序列.对这个序列有两个操作:(1)对区间进行翻转.也就是0变1,1变0.  (2)查询区间连续1的序列的最大长度 区间合并 ...

  2. poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新)

    好题.我做了很久,学了大牛们的区间搬移.主要的代码都有注释. #include<cstdio> #include<cstring> #include<iostream&g ...

  3. hust 1546 hdu 3911 Black And White

    题目描述 There are a bunch of stones on the beach; Stone color is white or black. Little Sheep has a mag ...

  4. Splay ---- 区间翻转 区间最大值 区间加 P4146 序列终结者

    题目链接 题目大意: 解题思路: 这是一道很入门的Splay的题目 但是第一次写有很多坑点 首先是maxmaxmax值的更新:就是因为这个点的最小值是会出现负数负数的,当你左右儿子有一个没有的话,那么 ...

  5. [置顶] hdu 1890 伸展树区间翻转

    题意: 给你n个数,每次先输出第i大的数的位置(如果有多个,选下标小的那个),然后每次将第i个位置到第i大的数所在位置之间的数进行翻转. 思路:输入的数组可能有多个相同的值,我们可以进行两次排序把数组 ...

  6. Splay ---- 2018牛客多校第三场 区间翻转搞区间位移 或者 rope可持久化块状链表

    题目链接 题目大意: 就是每次把牌堆中若干个连续的牌放到堆顶,问你最后牌的序列. 解题思路: Splay 区间翻转的模板题: 对于一个区间[1,2,3,4,5,6,7,8][1,2,3,4,5,6,7 ...

  7. Splay ---- 文艺平衡树区间翻转的建树模式

    Splay 的区间操作 这个splay已经不是平常的权值splay了, 每个节点维护区间的位置取决于它在树里面的位置 首先这课splay中序遍历的结果就是你维护的整个区间的数值!!注意这个中序遍历很重 ...

  8. CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换,清晰易懂)

    CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换)   首先一共有四个操作,第一个和第四个都是线段树的基本操作,直接用线段树实现.      第 ...

  9. BZOJ 3223: Tyvj 1729 文艺平衡树-Splay树(区间翻转)模板题

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 6881  Solved: 4213 [Submit][S ...

最新文章

  1. C++对C的加强之三目运算符功能增强
  2. struts2关键配置及函数总结,
  3. Py学生信息管理系统 案例(优化版)
  4. CreateProcess创建进程
  5. php-fpm 内存 facebook,【百家号】脸书百科,安装php-fpm-5.4.16-42.遇到的小问题 Web程序 - 贪吃蛇学院-专业IT技术平台...
  6. avro 序列化java_Avro 对象序列化与反序列化,及转Json对象序列化处理
  7. [原创]状态值在数据库中的检索
  8. win7 64位Apache http server+PHP配置
  9. Word2016以上版本兼容模式不能使用公式编辑器的解决办法
  10. 图片怎么去底色?怎么去图片背景为透明?
  11. 【Leetcode刷题Python】134. 加油站
  12. Linux下使用FastDFS
  13. 进程系列(一)-进程基本概念
  14. 编写MTK6737平台的GPIO驱动例程(六)
  15. 使用python绘制函数曲线
  16. “国防七子”、“C9联盟”、“华东五虎”,中国最顶尖的大学都在这!
  17. 使用Tycho构建OSGi插件项目
  18. 如何查看git账号以及如何切换登录git账号
  19. 学python第一弹 用IDLE启动python
  20. 如何把文档转成html格式转换,文档格式转换工具Print2Flash使用教程:如何将文档转换为Print2Flash格式件或HTML5文件?...

热门文章

  1. RecyclerView 删除Item 以及删除整个RecyclerView
  2. Vue 生命周期记录_学习笔记
  3. Java 成员变量与局部变量
  4. 微信小程序bindtap 与 catchtap 是使用
  5. px像素如何转为dip设备独立像素设备独立像
  6. 如何下载flash离线安装包
  7. Oracle数据库导入导出命令!
  8. 【BZOJ2140】稳定婚姻 Tarjan
  9. PCB的EMC设计之PCB叠层结构
  10. 十五天精通WCF——第六天 你必须要了解的3种通信模式