HDU - 3911 Black And White 区间翻转+区间连续最长
区间翻转的裸题,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 区间翻转+区间连续最长相关推荐
- 【线段树_区间合并_异或翻转】HDU 3911 Black And White
HDU 3911 Black And White 题意:有一个只有0和1组成的序列.对这个序列有两个操作:(1)对区间进行翻转.也就是0变1,1变0. (2)查询区间连续1的序列的最大长度 区间合并 ...
- poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新)
好题.我做了很久,学了大牛们的区间搬移.主要的代码都有注释. #include<cstdio> #include<cstring> #include<iostream&g ...
- 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 ...
- Splay ---- 区间翻转 区间最大值 区间加 P4146 序列终结者
题目链接 题目大意: 解题思路: 这是一道很入门的Splay的题目 但是第一次写有很多坑点 首先是maxmaxmax值的更新:就是因为这个点的最小值是会出现负数负数的,当你左右儿子有一个没有的话,那么 ...
- [置顶] hdu 1890 伸展树区间翻转
题意: 给你n个数,每次先输出第i大的数的位置(如果有多个,选下标小的那个),然后每次将第i个位置到第i大的数所在位置之间的数进行翻转. 思路:输入的数组可能有多个相同的值,我们可以进行两次排序把数组 ...
- Splay ---- 2018牛客多校第三场 区间翻转搞区间位移 或者 rope可持久化块状链表
题目链接 题目大意: 就是每次把牌堆中若干个连续的牌放到堆顶,问你最后牌的序列. 解题思路: Splay 区间翻转的模板题: 对于一个区间[1,2,3,4,5,6,7,8][1,2,3,4,5,6,7 ...
- Splay ---- 文艺平衡树区间翻转的建树模式
Splay 的区间操作 这个splay已经不是平常的权值splay了, 每个节点维护区间的位置取决于它在树里面的位置 首先这课splay中序遍历的结果就是你维护的整个区间的数值!!注意这个中序遍历很重 ...
- CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换,清晰易懂)
CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换) 首先一共有四个操作,第一个和第四个都是线段树的基本操作,直接用线段树实现. 第 ...
- BZOJ 3223: Tyvj 1729 文艺平衡树-Splay树(区间翻转)模板题
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 6881 Solved: 4213 [Submit][S ...
最新文章
- C++对C的加强之三目运算符功能增强
- struts2关键配置及函数总结,
- Py学生信息管理系统 案例(优化版)
- CreateProcess创建进程
- php-fpm 内存 facebook,【百家号】脸书百科,安装php-fpm-5.4.16-42.遇到的小问题 Web程序 - 贪吃蛇学院-专业IT技术平台...
- avro 序列化java_Avro 对象序列化与反序列化,及转Json对象序列化处理
- [原创]状态值在数据库中的检索
- win7 64位Apache http server+PHP配置
- Word2016以上版本兼容模式不能使用公式编辑器的解决办法
- 图片怎么去底色?怎么去图片背景为透明?
- 【Leetcode刷题Python】134. 加油站
- Linux下使用FastDFS
- 进程系列(一)-进程基本概念
- 编写MTK6737平台的GPIO驱动例程(六)
- 使用python绘制函数曲线
- “国防七子”、“C9联盟”、“华东五虎”,中国最顶尖的大学都在这!
- 使用Tycho构建OSGi插件项目
- 如何查看git账号以及如何切换登录git账号
- 学python第一弹 用IDLE启动python
- 如何把文档转成html格式转换,文档格式转换工具Print2Flash使用教程:如何将文档转换为Print2Flash格式件或HTML5文件?...