HDU 3397 双lazy标记的问题
题目大意
对一个只有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标记的问题的更多相关文章
- 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之间 ...
- HDU 1698 just a hook - 带有lazy标记的线段树(用结构体实现)
2017-08-30 18:54:40 writer:pprp 可以跟上一篇博客做个对比, 这种实现不是很好理解,上一篇比较好理解,但是感觉有的地方不够严密 代码如下: /* @theme:segme ...
- HDU 1698 Just a Hook 区间更新 lazy标记
lazy标记 #include <iostream> #include <cstdio> #include <cstring> #include <sstre ...
- 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变 ...
- hdu 3397 线段树双标记
Sequence operation Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- HDU1698 just a Hook - 带有lazy标记的线段树
2017-08-30 16:44:33 writer:pprp 上午刚刚复习了一下不带有lazy标记的线段树, 下午开始学带有lazy标记的线段树 这个是我看大佬代码敲的,但是出了很多问题, 这提醒我 ...
- HDU 3397 Sequence operation (区间合并,操作比较多)
费了我一天半的时间,到处debug,后来才发现,主要是建树的时候只在叶子节点对lazy1和lazy2进行初始化了,父节点都没初始化...晕. 具体见代码吧. #include <iostream ...
- POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)
题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每 ...
- poj3468 线段树+lazy标记
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 92921 ...
随机推荐
- poj2455Secret Milking Machine(二分+最大流)
链接 二分距离,小于当前距离的边容量+1,使最后流>=t 注意 会有重边 #include <iostream> #include<cstdio> #include< ...
- 【转】Java集合:HashMap源码剖析
Java集合:HashMap源码剖析 一.HashMap概述二.HashMap的数据结构三.HashMap源码分析 1.关键属性 2.构造方法 3.存储数据 4.调 ...
- codeforces415D. Glad to see you!(交互)
题意 交互题. 有$k$个值域为$[1, n]$的数. 请在不超过$60$次询问内找出其中的两个数. 每次询问形式为1 x y 交互库会返回$|x - a| <= |y - b| ? " ...
- P2712 摄像头
题目描述 食品店里有n个摄像头,这种摄像头很笨拙,只能拍摄到固定位置.现有一群胆大妄为的松鼠想要抢劫食品店,为了不让摄像头拍下他们犯罪的证据,他们抢劫前的第一件事就是砸毁这些摄像头. 为了便于砸毁摄像 ...
- C++模板类头文件和实现文件分离
http://www.cnblogs.com/lvdongjie/p/4288373.html 如何实现C++模板类头文件和实现文件分离,这个问题和编译器有关. 引用<<C++primer ...
- Java Web开发之Spring | SpringMvc | Mybatis | Hibernate整合、配置、使用
1.Spring与Mybatis整合 web.xml: <?xml version="1.0" encoding="UTF-8"?> <web ...
- Spotlight安装
刚才技术群的一个朋友在安装Spotligh出现了一些问题,所以本人临时写个简单的教程 1.下载安装包(安装包地址:https://pan.baidu.com/s/1c2tmqyc),解压,然后傻瓜式安 ...
- 工作笔记:复制文件--从windows到ubuntu,再到fedora
最近在测试跨平台类库,于是写了一些小程序. 当然主要利用vs进行主要的代码开发.eclipse进行linux的调试. 那么需要不时同步项目文件. 考虑到项目简单,所以没有使用svn. 1. 从wind ...
- python实战教程之自动扫雷(自己存下来学习之用)
3.python的第三方库win32api,win32gui,win32con,Pillow,numpy,opencv可通过 pip install --upgrade SomePackage 来进行 ...
- 前端什么是BFC
什么是BFC? 全称块级格式化上下文?什么意思不懂.看了好多博客,基本都是抄的,真心都不是大白话.我今天来总结一下,用菜鸟级别的语言来描述. BFC 应该可以抽象成一个 独立的个体,出淤泥而不染的白莲 ...