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 ...
随机推荐
- angularjs之ng-mode获取lobject类型里的键值
有时候数据库定义的时候,用一个对象来代表某个属性,之后直接访问对象就可以获取全部该对象的属性,但是有时需求访问对象中包含中的键值,引用键值的时候可以直接用.来获取对象的键值,比如 对象points: ...
- JAVA 运用流编程实现简单的"记事本"功能
一.概要 1.功能介绍 2.实现的思路及步骤代码 3.完整代码 二.功能 运用IO流和Swing实现简单的记事本功能(打开.保存.退出) 三.思路及实现步骤 1.在构造函数中画出操作界面 //创建jt ...
- Android设计模式——MVP
一.什么是MVP MVP:全称 Model-View-Presenter. MVP框架由3部分组成:View层负责显示,Presenter层负责逻辑处理,Model层提供数据. View:负责绘制UI ...
- Java_面向对象中的this和super用法
this: 1.使用在类中,可以用来修饰属性.方法.构造器 2.表示当前对象或者是当前正在创建的对象 3.当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须添加 this 来表明该变量时类成 ...
- AJPFX总结java 中类的创建和使用
//面向对象中类的创建和 调用 ============================================================= 类的使用: 类的使用分为两个动作:创建对象与 ...
- Android学习笔记(十七) BroadcastReceiver
1.接收广播 创建一个类,继承BroadcastReceiver,复写其中的onReceive()方法 在AndroidManifest.xml文件中注册该BroadcastReceiver 设置完成 ...
- Ubuntu 创建docker 容器 系列一
docker 官网安装地址:https://docs.docker.com/install/linux/docker-ce/ubuntu/ 1.Ubuntu的版本要在12.04 LTS 以上,使用un ...
- JavaFX Chart设置数值显示
一.XYChart import javafx.application.Application;import javafx.geometry.NodeOrientation;import javafx ...
- mysql中的 enum (枚举)
mysql enum是指字段的类型 表示枚举类型 mysql> alter table student add adders enum("sichuang","sh ...
- Java实现Web页面前数字字母验证码实现
最近公司做项目开发中用到了验证码实现功能,将实现代码分享出来, 前段页面实现代码: 为了表达清晰,样式部分代码去掉了,大家根据自己的需求,自己添加样式. 页面JS代码:触发变动验证码改变的JS 后台 ...