LCIS

Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12 Accepted Submission(s): 11
 
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
 
Author
notonlysuccess
 
Source
HDOJ Monthly Contest – 2010.02.06
 
Recommend
wxl
 
/*
题意:给你一个长度为n的序列,两种操作:U A B 将第A个数换成B,Q A B 询问区间[A B] 内的最长上升连续子序列的长度 初步思路:首先线段树要维护:此节点的区间 是不是靠左的,是不是靠右的,节点最长的上升子序列的长度,区间左边的值,右
边的值 #补充:区间合并的时候考虑的方面不全面,如果左儿子是完全的上升连续子序列,右儿子的上升连续子序列左右端点都不占,那
么这个时候,按照上面的思路,左右儿子就不能合并,这样的话,就会少了一种情况,节点需要维护的值加上,一个区间的
左端点,右端点,区间连续的长度。 #补充:区间合并已经没问题了,现在的问题就是查询的时候有bug,不能只考虑左右儿子,这样会漏掉很多种情况
*/
#include<bits/stdc++.h>
using namespace std;
/****************************线段树基础模板*********************************/
const int maxn=+; #define lson i*2, l, m
#define rson i*2+1, m+1, r
struct node{
int l,r,c;//区间左右端点,区间的长度
int val_l,val_r;//表示左边的值,表示右边的值
int res_l,res_m,res_r;//表示左端点,中间,右端点的最长连续上升子序列的长度
};
struct Segtree{ node sum[maxn<<]; void PushUp(int i)//向上更新节点 //× √
{
//分别比较左右儿子 //这个是不需要讨论的
sum[i].val_l=sum[i*].val_l;
sum[i].val_r=sum[i*+].val_r;
sum[i].res_l=sum[i*].res_l;//左边界的连续上升子序列的长度肯定是左儿子的
sum[i].res_r=sum[i*+].res_r;//右边界的连续上升子序列的长度肯定是右儿子的 sum[i].res_m=max(sum[i*].res_m,sum[i*+].res_m);//区间的连续上升子序列的长度肯定是的左右的最大值 if(sum[i*].val_r<sum[i*+].val_l){//左右区间可以对接,也就是可以合并的 if(sum[i*].res_l==sum[i*].c){//如果左儿子的区间是完全的上升连续序列 sum[i].res_l+=sum[i*+].res_l;//那么i节点的左边界的连续上升序列的长度还要加上右儿子的左边界的连续上升序列的长度
}
if(sum[i*+].res_r==sum[i*+].c){//如果右儿子的区间是完全的上升连续序列
sum[i].res_r+=sum[i*].res_r;
}
sum[i].res_m=max(sum[i].res_m,(sum[i*].res_r+sum[i*+].res_l) );//那么i节点的最长上升连续序列还要和左右区间接起来的比较一下
}
} void build(int i,int l,int r)
{
sum[i].l=l;
sum[i].r=r;
sum[i].c=r-l+;
if(l==r)//输入根节点的值并且初始化数据
{
scanf("%d",&sum[i].val_l);
sum[i].val_r=sum[i].val_l;
// cout<<"i= "<<i<<" "<<sum[i].val_l<<" "<<sum[i].val_r<<endl;
sum[i].res_r=sum[i].res_l=sum[i].res_m=;//从左开始的上升组序列的长度,右边的,中间的
return ;
} int m=(l+r)>>;
build(lson);
build(rson);
PushUp(i);
}
int query(int ql,int qr,int i,int l,int r)
{
if(ql<=l && r<=qr){
// cout<<"("<<l<<","<<r<<")"<<" sum[i].res_m="<<sum[i].res_m<<endl;
return sum[i].res_m;
} int m=(l+r)>>;
int res=;
if(ql<=m) res = max( res,query(ql,qr,lson) ); if(m<qr) res =max( res,query(ql,qr,rson) ); if(sum[*i].val_r < sum[*i+].val_l){//如果左右区间能接起来的话
// cout<<"i="<<i<<endl;
// cout<<"min(m-l+1,sum[2*i].res_r)="<<min(m-l+1,sum[2*i].res_r)<<" min(r-m,sum[2*i+1].res_l))="<<min(r-m,sum[2*i+1].res_l)<<endl;
// cout<<"m-l+1="<<m-l+1<<endl;
// cout<<"sum[2*i].res_r="<<sum[2*i].res_r<<endl;
// cout<<"r-m="<<r-m<<endl;
// cout<<"sum[2*i+1].res_l="<<sum[2*i+1].res_l<<endl;
res = max(res , min(m-ql+,sum[*i].res_r)+min(qr-m,sum[*i+].res_l));
}
return res;
} void update(int id,int val,int i,int l,int r)
{
if(l==r)//更新到根节点了
{
sum[i].val_l=sum[i].val_r=val;
return ;
}
int m=(l+r)>>;
if(id<=m) update(id,val,lson);
else update(id,val,rson); PushUp(i);//用来向上回溯
}
}segtree;
/****************************线段树基础模板*********************************/
int t;
int n,m;
char op[];
int a,b;
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
//输入
segtree.build(,,n); // for(int i=1;i<=25;i++){
// cout<<"*************************"<<endl;
// cout<<"i= "<<i<<endl;
// cout<<"l,r,c "<<segtree.sum[i].l<<" "<<segtree.sum[i].r<<" "<<segtree.sum[i].c<<endl;
// cout<<"val "<<segtree.sum[i].val_l<<" "<<segtree.sum[i].val_r<<endl;
// cout<<"res "<<segtree.sum[i].res_l<<" "<<segtree.sum[i].res_r<<" "<<segtree.sum[i].res_m<<endl;
// } for(int i=;i<m;i++){
scanf("%s",op);
// cout<<op<<" ";
if(op[]=='U'){//替换
scanf("%d%d",&a,&b);
// cout<<a<<" "<<b<<endl;
a++;
segtree.update(a,b,,,n); // cout<<"update a= "<<a<<" b="<<b<<endl;
// cout<<"l,r,c "<<segtree.sum[1].l<<" "<<segtree.sum[1].r<<" "<<segtree.sum[1].c<<endl;
// cout<<"val "<<segtree.sum[1].val_l<<" "<<segtree.sum[1].val_r<<endl;
// cout<<"res "<<segtree.sum[1].res_l<<" "<<segtree.sum[1].res_r<<" "<<segtree.sum[1].res_m<<endl;
// for(int i=1;i<=25;i++){
// cout<<"*************************"<<endl;
// cout<<"i= "<<i<<endl;
// cout<<"l,r,c "<<segtree.sum[i].l<<" "<<segtree.sum[i].r<<" "<<segtree.sum[i].c<<endl;
// cout<<"val "<<segtree.sum[i].val_l<<" "<<segtree.sum[i].val_r<<endl;
// cout<<"res "<<segtree.sum[i].res_l<<" "<<segtree.sum[i].res_r<<" "<<segtree.sum[i].res_m<<endl;
// }
}else{
scanf("%d%d",&a,&b);
// cout<<a<<" "<<b<<endl;
a++;
b++;
// cout<<"a="<<a<<" b="<<b<<endl;
printf("%d\n",segtree.query(a,b,,,n));
}
}
}
return ;
}

LCIS(区间合并)的更多相关文章

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

    LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  2. HDU 3308 LCIS (经典区间合并)【线段树】

    <题目链接> 题目大意: 给你一段序列,对其进行两种操作,一是修改某个序号的点的值:二是查询某个区间的LCIS(最长上升子序列). 解题分析: 线段树区间合并的典型例题,用求某个区间的LC ...

  3. hdu-3308 LCIS (线段树区间合并)

    LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

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

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

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

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

  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. 线段树的区间合并 B - LCIS

    B - LCIS HDU - 3308 这个是一个很简单很明显的线段树的区间合并,不过区间合并的题目都还是有点难写,建议存个板子. #include <cstdio> #include & ...

  8. [HDOJ3308]LCIS(线段树,区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题意:给定n个数,两个操作: U A B:将位置A的数值改成B Q A B:查询[A,B]内最长 ...

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

    题目大意:给一个整数序列,m次询问,每次询问某个区间中最长连续上升子序列的长度. 题目分析:线段树区间合并.维护以区间左端开头的.以区间右端点结尾的和区间最长的上升连续序列. 代码如下: # incl ...

随机推荐

  1. 新书发布《每天5分钟玩转Docker容器技术》

    后台不时收到关于纸质版教程书籍的询问,今天终于可以给大家一个交代了. <每天5分钟玩转Docker容器技术>现已在各大书城上架. 比较了一下,目前京东上最实惠:https://item.j ...

  2. ASP.NET Core 认证与授权[2]:Cookie认证

    由于HTTP协议是无状态的,但对于认证来说,必然要通过一种机制来保存用户状态,而最常用,也最简单的就是Cookie了,它由浏览器自动保存并在发送请求时自动附加到请求头中.尽管在现代Web应用中,Coo ...

  3. Excel的实用函数

    在介绍Excel函数前先说明两个概念:公式和函数. 公式:由用户自行设计对工作表进行计算和处理的计算式,以等号"="开始,其内部可以包括函数.引用.运算符和常量. 函数:即是预先定 ...

  4. 第4章 同步控制 Synchronization ----critical section 互斥区 ,临界区

    本章讨论 Win32 同步机制,并特别把重点放在多任务环境的效率上.撰写多线程程序的一个最具挑战性的问题就是:如何让一个线程和另一个线程合作.除非你让它们同心协力,否则必然会出现如第2章所说的&quo ...

  5. 【重点突破】——Cookie的使用

    cookie:小甜饼 cookie:保存客户端浏览器中一个纯文本文件 版本高的浏览器可查看   F12->Resource  左下方cookie    查看 cookie作用: 保存:[安全性要 ...

  6. 再起航,我的学习笔记之JavaScript设计模式28(委托模式)

    ## 委托模式 ### 概念介绍 **委托模式(Entrust): **多个对象接收并处理同一请求,他们将请求委托给另一个对象统一处理请求. ### 利用委托优化循环 如果我们有一个需求需要让用户点击 ...

  7. JS脚本检查密码强度

    <html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Con ...

  8. codesmith连接Mysql提示“找不到请求的 .Net Framework Data Provider。可能没有安装。"

    1,首先需要将MySql.Data.dll复制到codesmith安装目录下bin文件夹下,注意dll的版本 2,其次因为codesmith7采用的是.net4.0的配置文件,(64位系统)找到C:\ ...

  9. Windows系统下八大具有高逼格的DOS命令之一【ping】

    ping命令: ping是用来检测网络是否通畅或者查询网络连接速度的一个基础命令.作为一名对计算机痴迷的爱好者来说,ping命令是需要第一个掌握的DOS命令.它所利用的原理是这样的:网络上的机器都有唯 ...

  10. 【转载】CSS3 Transitions, Transforms和Animation使用简介与应用展示

    文章转载自 张鑫旭-鑫空间-鑫生活 http://www.zhangxinxu.com/wordpress/ 原文链接:http://www.zhangxinxu.com/wordpress/?p=1 ...