HDU 3911 Black And White(线段树区间合并+lazy操作)
开始以为是水题,结果。。。。。。
给你一些只有两种颜色的石头,0为白色,1为黑色。
然后两个操作:
1 l r 将[ l , r ]内的颜色取反
0 l r 计算[ l , r ]内最长连续黑色石头的个数
明显的线段树区间合并,记录lmax(从左端点开始的最长值) rmax(从右端点开始的最长值) 用于更新mmax(区间最长值)
但是这儿有区间更新,所以记录0的三个最长值和1的三个最长值,更新父节点的时候交换0与1就好。
还有这儿注意查询时,可能值在查询的几个子区间的的相邻处(因为我们只能查询子区间内的最大值,而答案却是几个子区间合在一起的其中某一段)。我们可以根据代码看出,区间查询时一定是从左端点依次不重不漏的进入几个子区间到右端点,所以我们计算最大值时就使用左边的rmax加上右边的lmax。具体看代码
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=<<;
const double Pi=acos(-1.0);
const int Max=<<;
struct node
{
int llmax,lrmax,lmmax;
int olmax,ormax,ommax;//最长的0个数 用于区间更新
}segtr[Max];
int upn[Max],tem;
int nmax(int a,int b)
{
return a>b?a:b;
}
void Upnow(int now,int next,int sum)//区间更新
{
segtr[now].lmmax=nmax(nmax(segtr[next].lmmax,segtr[next|].lmmax),segtr[next].lrmax+segtr[next|].llmax); segtr[now].llmax=segtr[next].llmax;
if(segtr[next].llmax==sum-(sum>>))
segtr[now].llmax+=segtr[next|].llmax; segtr[now].lrmax=segtr[next|].lrmax;
if(segtr[next|].lrmax==(sum>>))
segtr[now].lrmax+=segtr[next].lrmax; segtr[now].ommax=nmax(nmax(segtr[next].ommax,segtr[next|].ommax),segtr[next].ormax+segtr[next|].olmax); segtr[now].olmax=segtr[next].olmax;
if(segtr[next].olmax==sum-(sum>>))
segtr[now].olmax+=segtr[next|].olmax; segtr[now].ormax=segtr[next|].ormax;
if(segtr[next|].ormax==(sum>>))
segtr[now].ormax+=segtr[next].ormax;
return;
}
void Create(int sta,int enn,int now)
{
upn[now]=;
if(sta==enn)
{
scanf("%d",&tem);
if(tem)//开始tem为1
{
segtr[now].ommax=segtr[now].olmax=segtr[now].ormax=;
segtr[now].lmmax=segtr[now].llmax=segtr[now].lrmax=;
}
else
{
segtr[now].ommax=segtr[now].olmax=segtr[now].ormax=;
segtr[now].lmmax=segtr[now].llmax=segtr[now].lrmax=;
}
return;
}
int mid=dir(sta+enn,);
int next=mul(now,);
Create(sta,mid,next);
Create(mid+,enn,next|);
Upnow(now,next,enn-sta+);
return;
}
void Swap(int &a,int &b)
{
int t=a;
a=b;
b=t;
return;
}
void Cha(int now)//交换此段0与1的个数
{
Swap(segtr[now].lmmax,segtr[now].ommax);
Swap(segtr[now].llmax,segtr[now].olmax);
Swap(segtr[now].lrmax,segtr[now].ormax);
return;
}
void Downow(int now)
{
if(upn[now])
{
int next=mul(now,);
upn[next]=(+upn[next])%;
upn[next|]=(+upn[next|])%;
Cha(next);
Cha(next|);
upn[now]=;
}
return;
}
int ans,mmid;//最终结果 没有断开就继续加
void Update(int sta,int enn,int now,int x,int y,int z)//注意计算结果时虽然有回溯过程,但是一定是从**满足条件的最左边运行到最右边结束**
{
if(sta>=x&&enn<=y)
{
if(z)
{
upn[now]=(upn[now]+)%;
Cha(now);
}
else//**关键是两边区间有连接的情况**
{
mmid+=segtr[now].llmax;
ans=nmax(nmax(ans,mmid),segtr[now].lmmax);
if(segtr[now].llmax==enn-sta+);//整个区间相连
else
mmid=segtr[now].lrmax;
}
return;
}
Downow(now);
int mid=dir(sta+enn,);
int next=mul(now,);
if(mid>=x)
Update(sta,mid,next,x,y,z);
if(mid<y)
Update(mid+,enn,next|,x,y,z);
Upnow(now,next,enn-sta+);
return;
}
int main()
{
int n,m;
int p,lef,rig;
while(~scanf("%d",&n))
{
Create(,n,);
scanf("%d",&m);
while(m--)
{
scanf("%d %d %d",&p,&lef,&rig);
if(!p)
{
mmid=ans=;
Update(,n,,lef,rig,);
printf("%d\n",ans);
}
else
Update(,n,,lef,rig,);
}
}
return ;
}
HDU 3911 Black And White(线段树区间合并+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之间 ...
- UVA 1400."Ray, Pass me the dishes!" -分治+线段树区间合并(常规操作+维护端点)并输出最优的区间的左右端点-(洛谷 小白逛公园 升级版)
"Ray, Pass me the dishes!" UVA - 1400 题意就是线段树区间子段最大和,线段树区间合并,但是这道题还要求输出最大和的子段的左右端点.要求字典序最小 ...
- hdu 3911 Black And White(线段树)
题目连接:hdu 3911 Black And White 题目大意:给定一个序列,然后有M次操作: 0 l r:表示询问l,r中最大连续1的个数 1 l r:表示将l,r区间上的数取反 解题思路:线 ...
- HDU 3911 Black and White (线段树,区间翻转)
[题目地址] vjudge HDU [题目大意] 海滩上有一堆石头. 石头的颜色是白色或黑色. 小肥羊拥有魔术刷,她可以改变连续石的颜色,从黑变白,从白变黑. 小肥羊非常喜欢黑色,因此她想知道范围 ...
- HDU 1540 Tunnel Warfare(线段树+区间合并)
http://acm.hdu.edu.cn/showproblem.php?pid=1540 题目大意:抗日战争期间进行地道战,存在n个村庄用地道连接,输入D表示破坏某个村庄(摧毁与其相连的地道, 包 ...
- HDU - 1540 Tunnel Warfare(线段树区间合并)
https://cn.vjudge.net/problem/HDU-1540 题意 D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少. 分析 线段树的区间内,我 ...
- HDU 4553 约会安排(线段树区间合并+双重标记)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553 题目大意:就是有三种操作: ①DS x,安排一段长度为x的空闲时间跟屌丝一起,输出这段时间的起点 ...
- hdu 1540 Tunnel Warfare (线段树 区间合并)
Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...
- (简单) HDU 3397 Sequence operation,线段树+区间合并。
Problem Description lxhgww got a sequence contains n characters which are all '0's or '1's. We have ...
随机推荐
- 事件查看器事件ID部分说明
事件查看器从简单的查看电脑登录信息到检查系统是否出现错误,是否被入侵都有着很重要的作用,Microsoft为了简便,采用事件ID来代表一些信息,下面是我从Microsoft找来的WIN2003的对应关 ...
- MFC Initinstance中DoModal()返回-1
新建一个基于对话框的MFC应用程序,在App的Initinstance中调用对话框DoModal()来显示对话框,这是框架的内容,应用程序框架生成的全部是正常的. 当把我对话框的资源文件提取到一个资源 ...
- mysql无法启动
当在安装mysql服务时,有时会遇到恶心的PID错误而导致安装后无法启动以下为针对mysql-5.5版本在安装mysql时所遇到的问题的解决方法. 1.可能是/usr/local/mysql/data ...
- Html5 新标签
⒈ <audio></audio> 定义声音<autoplay></autoplay> 该属性出现,音频就绪后马上播放<controls>& ...
- 一个简单的代码计算行数demo编写
最近手头的项目基本上已经完结,历经了5个月的开发和迭代,各种的需求调整,想对自己的代码量进行一个客观的计算,于是抽了点时间写下了这个小demo,朋友们有需要的可以看看,很简单. 基本的思想就是:根目录 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(八) 之 用 Redis 实现用户在线离线状态消息处理
前言 上篇的预告好像是“聊天室的小细节,你都注意到了吗?”.今天也是为那篇做铺垫吧.之前的版本有好多问题,比如:当前登录用户是否合法问题,userid参数如果随便传后台没有验证.还有一个致命的问题,用 ...
- NYOJ题目596谁是最好的Coder
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAscAAAMaCAIAAADlQ3w8AAAgAElEQVR4nO3dO3LbvN4H4G8T7r2Q1F
- NYOJ之算菜价
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable ...
- Android Programming: Pushing the Limits -- Chapter 1: Fine-Tuning Your Development Environment
ADB命令 Application Exerciser Monkey Gradle ProGuard 代码重用 版本控制 静态代码分析 代码重构 开发者模式 ADB命令: @.adb help:查 ...
- 重温WCF之构建一个简单的WCF(一)(2)通过Windows Service寄宿服务和WCF中实现操作重载
参考地址:http://www.cnblogs.com/zhili/p/4039111.html 一.如何在Windows Services中寄宿WCF服务 第一步:创建Windows 服务项目,具体 ...