HDOJ 3308 LCIS (线段树)
题目:
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].
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).
思路:
单点更新 区间查询求最长连续上升子序列
这题的重点在于区间合并
线段树维护的值有三个 区间左端点开始的最长连续长度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 (线段树)的更多相关文章
- HDU 3308 LCIS (线段树区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...
- HDU 3308 LCIS 线段树区间更新
最近开始线段树一段时间了,也发现了不少大牛的博客比如HH大牛 ,小媛姐.这个题目是我在看HH大牛的线段树专题是给出的习题,(可以去他博客找找,真心推荐)原本例题是POJ3667 Hotel 这个题目 ...
- HDU 3308 LCIS(线段树单点更新区间合并)
LCIS Given n integers. You have two operations: U A B: replace the Ath number by B. (index counting ...
- HDU 3308 LCIS (线段树·单点更新·区间合并)
题意 给你一个数组 有更新值和查询两种操作 对于每次查询 输出相应区间的最长连续递增子序列的长度 基础的线段树区间合并 线段树维护三个值 相应区间的LCIS长度(lcis) 相应区间以左 ...
- hdu 3308 LCIS 线段树
昨天热身赛的简单版:LCIS.昨天那题用树链剖分,不知道哪里写错了,所以水了水这题看看合并.更新方式是否正确,发现没错啊.看来应该是在树链剖分求lca时写错了... 题目:给出n个数,有两种操作: 1 ...
- HDU 3308 LCIS(线段树)
题目链接 模板题吧,忘了好多,终于A了... #include <cstring> #include <cstdio> #include <string> #inc ...
- hud 3308 LCIS 线段树 区间合并
题意: Q a b 查询[a, b]区间的最长连续递增子序列的长度 U a b 将下表为a的元素更新为b 区间合并一般都有3个数组:区间最值,左区间最值和右区间最值 具体详见代码 #include & ...
- 线段树(区间合并) HDOJ 3308 LCIS
题目传送门 题意:线段树操作:1. 单点更新 2. 求区间的LCIS(longest consecutive increasing subsequence) 分析:注意是连续的子序列,就是简单的区间合 ...
- LCIS HDU - 3308 (线段树区间合并)
LCIS HDU - 3308 Given n integers. You have two operations: U A B: replace the Ath number by B. (inde ...
随机推荐
- vscode 配置踩坑记
vscode-easy-less 遇到问题最好的解决方式是看官网文档,切记!!! 在web开发当中,经常会写less然后编译成css,当然在VS Code当中也有这样的插件(EasyLess), 但是 ...
- VScode 1.13 gocode提示dial tcp 216.239.37.1:443: connectex: A connection attempt failed because the connected..
在将VScode升级至 1.13后让升级gocode,在升级时报出如下错误 D:\go_work\src>go get -u -v github.com/mdempsky/gocode gith ...
- js学习总结:DOM节点一(选择器,节点类型)
DOM:document object model 文档对象模型 DOM就是整个HTML文档的关系图谱(代表整个HTML文档),可以理解为下图: 一.查看元素节点 1.document.getElem ...
- ZooKeeper基础CRUD操作
==============================Curator Java 客户端 CRUD 使用==============================Curator 是 Apache ...
- 安装Rational Rose后提示java.lang.ClassNotFoundException
1. 在运行中输入regedit回车,打开注册表编辑器2. 搜索 TrustedClasspath [REG_SZ] ,因为64位和32位不一样. 4.添加值c:\windows\java\trust ...
- Visual Studio 2013 更新 NuGet 包管理器
Ø 前言 使用 Visual Studio 中的 NuGet 包管理器下载程序时,有时可能出现类似的错误:. 5. 在"联机"选项中搜索"NuGet",选 ...
- 经典文摘:饿了么的 PWA 升级实践(结合Vue.js)
自 Vue.js 官方推特第一次公开到现在,我们就一直在进行着将饿了么移动端网站升级为 Progressive Web App 的工作.直到近日在 Google I/O 2017 上登台亮相,才终于算 ...
- 二十五、Linux 进程与信号---exec函数
25.1 介绍 在用 fork 函数创建子进程后,子进程往往要调用一种 exec 函数以执行另一个程序 当进程调用一种 exec 函数时,该进程完全由新程序代换,替换原有进程的正文,而新程序则从其 m ...
- vue安装教程总结
转载:https://blog.csdn.net/sunny1660/article/details/78326548 简介: vue.js是一套构建用户界面的渐进式框架.比较简洁,用于解 ...
- cpp 常量函数(函数后加const)
const用在成员函数后 主要是针对类的const 对象 如: class Text{ public: void printconst(void)const{cout<<" ...