最近开始线段树一段时间了,也发现了不少大牛的博客比如HH大牛  ,小媛姐。这个题目是我在看HH大牛的线段树专题是给出的习题,(可以去他博客找找,真心推荐)原本例题是POJ3667
Hotel
 这个题目,是一个求连续空区间的情况,而hdoj这个题目是求给定区间单调连续的最大区间长度,两个题目思路很相似,将节点rt用sum[rt],lsum[rt],rsum[rt]来描述,分别表示rt对应区间即[l,r]内满足条件的区间的最大长度,从左边端点l开始满足条件的最大区间长度,从右边r开始向左的满足条件的最大区间长度。

void PushUp(int rt,int m,int mid)//mid表示更新区间的中点,m表示长度

{

    lsum[rt]=lsum[rt<<1];

    rsum[rt]=rsum[rt<<1|1];

    int t=1;

    if(A[mid]<A[mid+1])

    {

        if(lsum[rt]==(m-(m>>1)))

            lsum[rt]+=lsum[rt<<1|1];

        if(rsum[rt]==(m>>1))

            rsum[rt]+=rsum[rt<<1];

        t= rsum[rt<<1]+lsum[rt<<1|1];

    }

       sum[rt]=max(t,max(sum[rt<<1],sum[rt<<1|1]));

}

PushUp函数和query函数是关键  ,PushUp函数向上更新时,先将lsum[rt]用

lsum[rt<<1]也就是左子区间左边开始的最大长度,如果这个区间长度刚好是l到mid之间的长度,说明区间已经穿过中点了,应该在加上右子区间lsum[rt<<1|1]这部分,类似的可以更新rsum[rt]。对于sum[rt]应该对应rsum[rt<<1]+lsum[rt<<1|1],sum[rt<<1],sum[rt<<1|1]三种情况中的最大值,因为满足条件的最长单调区间可以是左半部分,右半部分,或者贯穿中点。

理解了这部分那么query函数可以按照类似的思路来写,但要注意的是对于贯穿中点的判断条件是A[mid]<A[mid+1],这样才能将两部分加起来。

期间又一次犯二TLE了,原本是用C写的,max函数是用的宏定义,结果里面含有query函数,这样最终可能会两次调用query函数,不超时才怪,好在以前犯过一次,被基友发现了,改成algorithm里面的max就过了。哎,有个能debug基友就是好啊。hhha~

#include<cstdio>

#include<cstring>
#include<algorithm>
#define N 100010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 using namespace std;
int sum[N<<2],rsum[N<<2],lsum[N<<2],A[N]; void PushUp(int rt,int m,int mid)
{
lsum[rt]=lsum[rt<<1];
rsum[rt]=rsum[rt<<1|1];
int t=1;
if(A[mid]<A[mid+1])
{
if(lsum[rt]==(m-(m>>1)))
lsum[rt]+=lsum[rt<<1|1];
if(rsum[rt]==(m>>1))
rsum[rt]+=rsum[rt<<1];
t= rsum[rt<<1]+lsum[rt<<1|1];
}
sum[rt]=max(t,max(sum[rt<<1],sum[rt<<1|1]));
} void build(int l,int r,int rt)
{
if(l==r)
{
sum[rt]=lsum[rt]=rsum[rt]=1;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUp(rt,r-l+1,m);
} void update(int p,int l,int r,int rt)
{
if(l==r)
return;
int m=(l+r)>>1;
if(p<=m)
update(p,lson);
else update(p,rson);
PushUp(rt,r-l+1,m);
} int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
return sum[rt];
}
int m=(l+r)>>1;
if(l==r)
return 1;
int ans=0;
if(R<=m)
ans=max(ans,query(L,R,lson));
else if(L>m)
ans=max(ans,query(L,R,rson));
else
{
ans=max(ans,query(L,R,lson));
ans=max(ans,query(L,R,rson));
int ll,rr;
if(m-L+1>=rsum[rt<<1])
ll=rsum[rt<<1];
else ll=m-L+1;
if(R-m>=lsum[rt<<1|1])
rr=lsum[rt<<1|1];
else rr=R-m;
ans=max(ans,ll);
ans=max(ans,rr);
if(A[m+1]>A[m])
ans=max(ans,ll+rr);
}
return ans;
} int main(void)
{
int T;
int n,m,a,b;
char op[3];
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
scanf("%d",A+i);
build(1,n,1);
while(m--)
{
scanf("%s%d%d",op,&a,&b);
if(op[0]=='U')
{
A[a+1]=b;
update(a+1,1,n,1);
}
else
{
int ans=query(a+1,b+1,1,n,1);
printf("%d\n",ans);
}
}
}
return 0;
}

HDU 3308 LCIS 线段树区间更新的更多相关文章

  1. HDU 3308 LCIS (线段树区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...

  2. HDU 3308 LCIS(线段树单点更新区间合并)

    LCIS Given n integers. You have two operations: U A B: replace the Ath number by B. (index counting ...

  3. hdu 4031 attack 线段树区间更新

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Subm ...

  4. LCIS线段树(区间更新)

    首先线段树每一个节点包含:[b,e],lmax,rmax,max;其中lmax表示从左端点开始连续的最长的增序列长度,rmax表示从e端点开始向左连续的最长下降序列长度,max表示当前区间的连续递增的 ...

  5. HDU 3308 LCIS (线段树&#183;单点更新&#183;区间合并)

    题意  给你一个数组  有更新值和查询两种操作  对于每次查询  输出相应区间的最长连续递增子序列的长度 基础的线段树区间合并  线段树维护三个值  相应区间的LCIS长度(lcis)  相应区间以左 ...

  6. LCIS HDU - 3308 (线段树区间合并)

    LCIS HDU - 3308 Given n integers. You have two operations: U A B: replace the Ath number by B. (inde ...

  7. HDU 3308 (线段树区间合并)

    http://acm.hdu.edu.cn/showproblem.php?pid=3308 题意: 两个操作  : 1 修改 单点  a 处的值. 2 求出 区间[a,b]内的最长上升子序列. 做法 ...

  8. HDU 5861 Road 线段树区间更新单点查询

    题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5861 Road Time Limit: 12000/6000 MS (Java/Othe ...

  9. hdu 1698(线段树区间更新)

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

随机推荐

  1. Java反序列化

    一.序列化和反序列化的概念       把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬 ...

  2. CSS样式表介绍

    一.    CSS中的样式选择 1)内样式(内联样式) style=””; 2)内嵌样式 <style type="text/css"></style> 3 ...

  3. oracle从各个表取得数据保存到另一个表

    从各个表中取得数据保存另一个表中: CREATE VIEW PARAMETER_view ASWITH tall AS ( SELECT p.PI_NO,--产品序列号 p.SERIALNO,--产品 ...

  4. Library cache lock 故障解决一例

    今天收到同事电话,说是数据库中一张名为acct_balance进行操作是奇慢,第一反映是不是扫行计划有问题,结果我错了,现将过程记录下来. 用pl/sql连上数据库情况:1.对acct_balance ...

  5. iOS 计算两个日期之间的天数问题

    //获取当前时间若干年.月.日之后的时间 + (NSDate *)dateWithFromDate:(NSDate *)date years:(NSInteger)years months:(NSIn ...

  6. swift-08-使用键值对儿统计字符在字符串中出现的次数

    // //  main.swift //  12- // //  Created by wanghy on 15/8/9. //  Copyright (c) 2015年 wanghy. All ri ...

  7. thinkphp 模板中赋值

    在项目开发的时候,有时候希望直接在模板中调用 一些自定义方法,或者内置方法来,处理获得一些数据,并且赋值给一个变量给后面调用,这个时候如果用原生Php 的方式调用如下:<?php $abc = ...

  8. 用crontab、crond在嵌入式系统中添加定时任务

    在嵌入式系统中,定时任务通过crond和cronttab两个系统命令来联合执行. 其中crond是定时任务的守护进程,系统开始时是没有开启的.crontab主要作用是管理用户的crontab file ...

  9. Codevs 3731 寻找道路 2014年 NOIP全国联赛提高组

    3731 寻找道路 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找 ...

  10. Gradle教程之任务管理

    简要概述依赖管理 不算完美的依赖管理技术 自动管理依赖的重要性 自动依赖管理面临的挑战 声明依赖 外部模块依赖 文件依赖 配置远程仓库 这一章我将介绍Gradle对依赖管理的强大支持,学习依赖分组和定 ...