题目:

Problem Description
Given n integers.
You have two operations:
U A B: replace the Ath number by B. (index counting from 0)
Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b].
 
Input
T in the first line, indicating the case number.
Each case starts with two integers n , m(0<n,m<=105).
The next line has n integers(0<=val<=105).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=105)
OR
Q A B(0<=A<=B< n).
 
Output
For each Q, output the answer.
 
Sample Input
1
10 10
7 7 3 3 5 9 9 8 1 8
Q 6 6
U 3 4
Q 0 1
Q 0 5
Q 4 7
Q 3 5
Q 0 2
Q 4 6
U 6 10
Q 0 9
 
Sample Output
1
1
4
2
3
1
2
5

思路:

单点更新 区间查询求最长连续上升子序列

这题的重点在于区间合并

线段树维护的值有三个 区间左端点开始的最长连续长度lsum 区间右端点结束的最长连续长度 区间内最长连续长度

在向上更新的部分 要考虑一个特殊情况 即左儿子的右端点值小于右儿子的左端点值 代表至少在这两个点上是连续上升的

此时 如果左儿子的lsum大于左儿子的区间长度 代表左儿子的左端点开始的连续上升区间是左儿子的整个区间加上右儿子的左端点开始的连续上升区间 对这两个区间进行合并

同理 如果右儿子的rsum大于右儿子的区间长度 代表右儿子的右端点结束的连续上升区间是右儿子的整个区间加上左儿子的右端点结束的连续上升区间 对这两个区间进行合并

最后在进行区间查询的时候 如果左儿子的右端点值小于右儿子的左端点值 则还要考虑这两个区间加起来的情况 是否存在更长的连续上升区间


代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm> using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int maxn=1e5+;
int n,m,a,b,t,ans;
int x[maxn];
char op[]; struct node{
int l,r; //左右边界与连续的长度
int ls,rs; //左右边界的值
int lsum,rsum,sum; //左右最大LCIS 区间最大LCIS
}tree[maxn*]; void pushup(int rt){
tree[rt].ls=tree[rt*].ls;
tree[rt].rs=tree[rt*+].rs;
tree[rt].lsum=tree[rt*].lsum;
tree[rt].rsum=tree[rt*+].rsum;
tree[rt].sum=max(tree[rt*].sum,tree[rt*+].sum);
if(tree[rt*].rs<tree[rt*+].ls){//如果左子树的右边界值小于右子树的左边界值 合并左子树的右边界和右子树的左边界进行计算
if(tree[rt*].lsum==(tree[rt*].r-tree[rt*].l+)){
tree[rt].lsum+=tree[rt*+].lsum;
}
if(tree[rt*+].rsum==(tree[rt*+].r-tree[rt*+].l+)){
tree[rt].rsum+=tree[rt*].rsum;
}
tree[rt].sum=max(tree[rt].sum,tree[rt*].rsum+tree[rt*+].lsum);
}
} void build(int l,int r,int rt){
tree[rt].l=l;
tree[rt].r=r;
if(l==r){
tree[rt].lsum=tree[rt].rsum=tree[rt].sum=;
tree[rt].ls=tree[rt].rs=x[l];
return;
}
int mid=(l+r)/;
build(l,mid,rt*);
build(mid+,r,rt*+);
pushup(rt);
} void update(int rt){
if(tree[rt].l==tree[rt].r){
tree[rt].ls=tree[rt].rs=b;
return;
}
int mid=(tree[rt].l+tree[rt].r)/;
if(a<=mid) update(rt*);
else update(rt*+);
pushup(rt);
} int query(int rt){
if(tree[rt].l>=a && tree[rt].r<=b){
return tree[rt].sum;
}
int mid=(tree[rt].l+tree[rt].r)/;
int ans=;
if(a<=mid) ans=max(ans,query(rt*));
if(b>mid) ans=max(ans,query(rt*+));
if(tree[rt*].rs<tree[rt*+].ls)
ans=max(ans,min(mid-a+,tree[rt*].rsum)+min(b-mid,tree[rt*+].lsum));
return ans;
} int main(){
// freopen("data.in","r",stdin);
// freopen("2.out","w",stdout);
scanf("%d",&t);
for(int id=;id<=t;id++){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%d",&x[i]);
}
build(,n,);
for(int i=;i<=m;i++){
scanf("%s%d%d",op,&a,&b);
if(op[]=='U'){
a++;
update();
}
if(op[]=='Q'){
a++;b++;
printf("%d\n",query());
}
}
}
return ;
}

HDOJ 3308 LCIS (线段树)的更多相关文章

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

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

  2. HDU 3308 LCIS 线段树区间更新

    最近开始线段树一段时间了,也发现了不少大牛的博客比如HH大牛  ,小媛姐.这个题目是我在看HH大牛的线段树专题是给出的习题,(可以去他博客找找,真心推荐)原本例题是POJ3667 Hotel 这个题目 ...

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

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

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

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

  5. hdu 3308 LCIS 线段树

    昨天热身赛的简单版:LCIS.昨天那题用树链剖分,不知道哪里写错了,所以水了水这题看看合并.更新方式是否正确,发现没错啊.看来应该是在树链剖分求lca时写错了... 题目:给出n个数,有两种操作: 1 ...

  6. HDU 3308 LCIS(线段树)

    题目链接 模板题吧,忘了好多,终于A了... #include <cstring> #include <cstdio> #include <string> #inc ...

  7. hud 3308 LCIS 线段树 区间合并

    题意: Q a b 查询[a, b]区间的最长连续递增子序列的长度 U a b 将下表为a的元素更新为b 区间合并一般都有3个数组:区间最值,左区间最值和右区间最值 具体详见代码 #include & ...

  8. 线段树(区间合并) HDOJ 3308 LCIS

    题目传送门 题意:线段树操作:1. 单点更新 2. 求区间的LCIS(longest consecutive increasing subsequence) 分析:注意是连续的子序列,就是简单的区间合 ...

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

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

随机推荐

  1. centos7.2安装完成的基本操作

    系统是centos7.2,安装完成的基本操作 1 修改网卡为eth02 更新系统3 给/etc/rc.local添加执行权限4 添加用户hequan5 禁用selinux6 关闭防火墙安装iptabl ...

  2. Spring Boot笔记十:IOC控制反转

    目录 IOC控制反转和DI依赖注入 IOC实现Hello World Spring IOC容器怎么知道哪些是管理的对象? IOC容器getBean方法的三种签名 xml配置文件的import导入 @A ...

  3. java io系列22之 FileReader和FileWriter

    FileReader 是用于读取字符流的类,它继承于InputStreamReader.要读取原始字节流,请考虑使用 FileInputStream.FileWriter 是用于写入字符流的类,它继承 ...

  4. angular,vue,react的基本语法—动态属性、事件绑定、ref,angular组件创建方式

    基本语法: 动态属性: vue: v-bind:attr="msg" :attr="msg" react: attr={msg} angular [attr]= ...

  5. SQL Server2012安装流程

    今天手比较抽风,把原来的SQL Server给卸载了,卸载还卸了半天,真是…… 安装时找了好多教程,结果都不是很详细,然后准备自己摸索一下,把这个过程记录下来,供大家参考,如果有不当的地方,欢迎指正, ...

  6. 自学python 3.

    1.name = "aleX leNb" 1.a = name.strip() print(a) 2.a = name.lstrip('al') print(a) 3.a = na ...

  7. Native/Webview bridge for Hybrid

    Native/Webview bridge for Hybrid 安装 npm i --save webview-bridge 特点 支持自定义app URL scheme 支持多种处理方式(全部涵盖 ...

  8. Tomcat配置到JEE版eclipse中

    接我上篇文中的tomcat下载,及环境变量配置,http://blog.csdn.net/qq_40223688/article/details/79451468 这篇文章我就讲一下怎么把tomcat ...

  9. 三十六、Linux 线程——线程基本概念及线程的创建和终止

    36.1 线程介绍 36.1.1 线程的基本概念 进程是资源管理的最小单位,线程是程序执行的最小单位 每个进程都有自己的数据段.代码段和堆栈段. 线程通常叫做轻型的进程,它包含独立的栈和 CPU 寄存 ...

  10. GCC编译器原理(二)------编译原理一:ELF文件(2)

    四. ELF 文件格式分析 ELF文件(目标文件)格式主要四种: 可重定向文件: 文件保存着代码和适当的数据,用来和其他的目标文件一起来创建一个可执行文件或者是一个共享目标文件.(目标文件或者静态库文 ...