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 区间合并求最大长度的问题的更多相关文章

  1. Tunnel Warfare HDU 1540 区间合并+最大最小值

    Tunnel Warfare HDU 1540 区间合并+最大最小值 题意 D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点. 题解思路 参考的大佬博客 这里 ...

  2. E - Tunnel Warfare HDU - 1540 F - Hotel G - 约会安排 HDU - 4553 区间合并

    E - Tunnel Warfare HDU - 1540 对这个题目的思考:首先我们已经意识到这个是一个线段树,要利用线段树来解决问题,但是怎么解决呢,这个摧毁和重建的操作都很简单,但是这个查询怎么 ...

  3. POJ 4718 /// 树链剖分+线段树区间合并 求树上两点间的LCIS长度

    题目大意: 给定n个点 每个点都有权值 接下来给定树的n条边 第 i 个数 a[i] 表示 i+1到a[i]之间 有一条边 给定q q个询问 每次询问给出 x y 求x到y的最长上升子序列的长度 题解 ...

  4. HDU 1540 区间合并线段树

    题目大意: 就是给定一堆位置,进行删除还原,最后找到 t 位置上的最大连续位置 #include <cstdio> #include <cstring> #include &l ...

  5. HDU 3911 线段树区间合并、异或取反操作

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...

  6. hdu 3911 Black And White (线段树 区间合并)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911 题意: 给你一段01序列,有两个操作: 1.区间异或,2.询问区间最长的连续的1得长度 思路: ...

  7. 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之间 ...

  8. hdu 1540 Tunnel Warfare 线段树 单点更新,查询区间长度,区间合并

    Tunnel Warfare Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...

  9. HDU 3308 线段树求区间最长连续上升子序列长度

    题意:两种操作,Q L R查询L - R 的最长连续上升子序列长度,U pos val 单点修改值 #include <bits/stdc++.h> #define N 100005 us ...

随机推荐

  1. Backbone学习记录(2)

    创建一个集合 1)new Backbone.Collection()方式 var user=new Backbone.Model({'name':'susan'}); var list=new Bac ...

  2. web简单的整体测试

    网站性能压力测试是性能调优过程中必不可少的一环.只有让服务器处在高压情况下才能真正体现出各种设置所暴露的问题 ab测试 ab命令会创建很多的并发访问线程,模拟多个访问者同时对某一URL地址进行访问.它 ...

  3. RHEL 6.5----Varnish缓存服务器

    主机名 IP  服务  master  192.168.30.130   varnish   slave  192.168.30.131  httpd WebServer   192.168.30.1 ...

  4. PDO相关函数

    (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0) PDO::__construct — 创建一个表示数据库连接的 PDO 实例 说明 PDO::__co ...

  5. [转]如何使用MFC和类型库创建自动化项目

    本文转自:http://www.cnblogs.com/zhoug2020/archive/2012/04/01/2429064.html 摘要 本文详细介绍了如何自动化像Microsoft Offi ...

  6. idea使用Git提交代码时忽略指定文件或文件夹

    简述 使用idea编写代码并使用git作为版本控制器的时候,常常不需要提交配置文件以及一些其他不需要提交的文件,可以使用.ignore插件来在上传的时候忽略一些文件或文件夹. 安装 注意:安装完成之后 ...

  7. 微信小程序 开放能力学习

    1. 用户信息小程序登录使用微信的个人信息快速搭建用户体系,登录逻辑:小程序向微信获取code 给服务端生成用户. 说明1. 小程序端调用 wx.login() 获取临时登录凭证 code,并传到服务 ...

  8. 【学习笔记】OSG 基本几何图元

    例:geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4)); 来指定要利用这些数据生成一个怎么样的形状. ...

  9. 【转载】Hierarchal Temporal Memory (HTM)

    最近在看机器学习,看能否根据已有的历史来预测Hardware的故障发生概率.下文是一篇很有意思的文章,转自 http://numenta.org/htm.html. NuPIC是一个开源项目,用来实现 ...

  10. Java 利用FTP上传,下载文件,遍历文件目录

    Java实现FTP上传下载文件的工具包有很多,这里我采用Java自带的API,实现FTP上传下载文件.另外JDK1.7以前的版本与其之后版本的API有了较大的改变了. 例如: JDK1.7之前 JDK ...