HDU 3911 区间合并求最大长度的问题
http://vjudge.net/problem/viewProblem.action?id=21557
题目大意:
每进行一次颜色改变都可以把一段区间内的黑石头变成白石头,白石头变成黑石头,最后问区间内黑石头连续的最大长度
这里我们可以用rev[]作为lazy标记,每次进行改变,rev[]^1
因为有黑白两种石头,我们求连续区间,需要维护黑,白两种石头的左侧最多,右侧最多和全部最多,所以我们这里可以用一个二维数组进行描述
每次做出改变,只要将黑白石头的值进行交换即可就方便了很多
对于最后访问的时候做的区间合并。。。。我确实有点拙计了,最后是学长帮忙改正的。。。。
还是有点只会套模板的嫌疑Orz,关键模板的代码是不考虑处在两个不同的区间进行合并的情况的,所以最后在所有 单个区间的情况判断完后,我们
要把左子树的右侧和右子树的左侧合并到一起,因为可能会超过访问范围,所以这里用的是:
ans = max(ans,min(mid-s+1,rc[ls][1])+min(t-mid,lc[rs][1]));
在内部取个最小值。
在此将自己拙计的query函数和正确的query函数进行一下对比:
/*
void query(int cur ,int x,int y,int s,int t,int &ans)
{
int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
if(x>=s&&y<=t){
ans+=mc[cur][1];
return;
}
push_down(cur,x,y);
if(mid>=s) query(L,s,t,ans);
if(mid+1<=t) query(R,s,t,ans);
}*/ int query(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,query(L,s,t));
if(mid+<=t) ans = max(ans,query(R,s,t));
ans = max(ans,min(mid-s+,rc[ls][])+min(t-mid,lc[rs][]));
return ans;
}
总代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100010
#define L ls,x,mid
#define R rs,mid+1,y
int color[N],rev[N<<],lc[N<<][],rc[N<<][],mc[N<<][];
void push_up(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
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[rs][i]+rc[ls][i];
}
}
void push_down(int cur,int x,int y)
{
int ls=cur<<,rs=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][]); rev[cur]=;
}
}
void build(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
rev[cur]=;
if(x==y){
lc[cur][]=rc[cur][]=mc[cur][]=color[x]^;
lc[cur][]=rc[cur][]=mc[cur][]=color[x];
return;
}
build(L);
build(R);
push_up(cur,x,y);
}
void update(int cur,int x,int y,int s,int t)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(x>=s&&y<=t){
swap(lc[cur][],lc[cur][]);
swap(rc[cur][],rc[cur][]);
swap(mc[cur][],mc[cur][]);
rev[cur]^=;
return;
}
push_down(cur,x,y);
if(mid>=s) update(L,s,t);
if(mid+<=t) update(R,s,t);
push_up(cur,x,y);
}
/*
void query(int cur ,int x,int y,int s,int t,int &ans)
{
int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
if(x>=s&&y<=t){
ans+=mc[cur][1];
return;
}
push_down(cur,x,y);
if(mid>=s) query(L,s,t,ans);
if(mid+1<=t) query(R,s,t,ans);
}*/ int query(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,query(L,s,t));
if(mid+<=t) ans = max(ans,query(R,s,t));
ans = max(ans,min(mid-s+,rc[ls][])+min(t-mid,lc[rs][]));
return ans;
}
int main()
{
int n,m,op,a,b;
while(scanf("%d",&n)!=EOF){
for(int i=;i<=n;i++) scanf("%d",&color[i]);
build(,,n);
scanf("%d",&m);
for(int i=;i<m;i++){
scanf("%d%d%d",&op,&a,&b);
if(op) update(,,n,a,b);
else{
//int ans=0;
//query(1,1,n,a,b,ans);
printf("%d\n",query(,,n,a,b));
}
}
}
return ;
}
HDU 3911 区间合并求最大长度的问题的更多相关文章
- Tunnel Warfare HDU 1540 区间合并+最大最小值
Tunnel Warfare HDU 1540 区间合并+最大最小值 题意 D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点. 题解思路 参考的大佬博客 这里 ...
- E - Tunnel Warfare HDU - 1540 F - Hotel G - 约会安排 HDU - 4553 区间合并
E - Tunnel Warfare HDU - 1540 对这个题目的思考:首先我们已经意识到这个是一个线段树,要利用线段树来解决问题,但是怎么解决呢,这个摧毁和重建的操作都很简单,但是这个查询怎么 ...
- POJ 4718 /// 树链剖分+线段树区间合并 求树上两点间的LCIS长度
题目大意: 给定n个点 每个点都有权值 接下来给定树的n条边 第 i 个数 a[i] 表示 i+1到a[i]之间 有一条边 给定q q个询问 每次询问给出 x y 求x到y的最长上升子序列的长度 题解 ...
- HDU 1540 区间合并线段树
题目大意: 就是给定一堆位置,进行删除还原,最后找到 t 位置上的最大连续位置 #include <cstdio> #include <cstring> #include &l ...
- HDU 3911 线段树区间合并、异或取反操作
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...
- hdu 3911 Black And White (线段树 区间合并)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911 题意: 给你一段01序列,有两个操作: 1.区间异或,2.询问区间最长的连续的1得长度 思路: ...
- 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 1540 Tunnel Warfare 线段树 单点更新,查询区间长度,区间合并
Tunnel Warfare Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...
- HDU 3308 线段树求区间最长连续上升子序列长度
题意:两种操作,Q L R查询L - R 的最长连续上升子序列长度,U pos val 单点修改值 #include <bits/stdc++.h> #define N 100005 us ...
随机推荐
- 摄像头调用,h5调用摄像头进行扫一扫插件备份
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- vs2013转为vs2010项目
1.首先用记事本之类的工具打开.sln文件 打开后会看到如下信息 Format Version 12.00 就是指VS2013 VisualStudioVersion = 12.0.21005.1 指 ...
- CCF|火车购票|Java|80分
import java.util.*; public class Main { public static void main(String[] args) { Scanner in = new Sc ...
- Kotlin学习的一些心得
1.工程manifest中的application节点有冲突时,添加 xmlns:tools="http://schemas.android.com/tools" tools:re ...
- java中properties的使用实例
package com.ywx.io; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputSt ...
- Vue 组件 data为什么是函数
在创建或注册模板的时候,传入一个data属性作为用来绑定的数据.但是在组件中,data必须是一个函数,而不能直接把一个对象赋值给它. Vue.component('my-component', { t ...
- elasticsearch httpclient认证机制
最近公司单位搬迁,所有的服务都停止了,我负责的elasticsearch不知道怎么回事,一直不能运行呢,因此,我一直在负责调试工作.经过两天的调试工作,我发现新的服务器增加了httpclient认证机 ...
- 一次执行两个npm "start": "concurrently 'npm:dev' 'npm:json-server'"
用的这个程序 concurrently 说是再有异步的时候,&& 就不好使,而且&& 也不能执行npm 只能执行命令 官方地址:https://www.npmjs.co ...
- qobject_cast
void QLadderDiagramItem::GetMainForm(DoType sourceType){ for each (QWidget *w in qApp->topLevelWi ...
- nvm、npm、nodejs的关系(转载)
nvm.npm.nodejs的关系 为什么要了解nvm.npm.nodejs的关系: reactNative的项目构建都是有这几个工具进行构建管理. 掌握他们的关系,就能了解reactNative项目 ...