LCIS(区间合并)
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 |
|
Sample Output
1 |
|
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(区间合并)的更多相关文章
- LCIS(线段树区间合并)
LCIS Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- HDU 3308 LCIS (经典区间合并)【线段树】
<题目链接> 题目大意: 给你一段序列,对其进行两种操作,一是修改某个序号的点的值:二是查询某个区间的LCIS(最长上升子序列). 解题分析: 线段树区间合并的典型例题,用求某个区间的LC ...
- hdu-3308 LCIS (线段树区间合并)
LCIS Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDU 3308 LCIS (线段树·单点更新·区间合并)
题意 给你一个数组 有更新值和查询两种操作 对于每次查询 输出相应区间的最长连续递增子序列的长度 基础的线段树区间合并 线段树维护三个值 相应区间的LCIS长度(lcis) 相应区间以左 ...
- 线段树(区间合并) 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 ...
- 线段树的区间合并 B - LCIS
B - LCIS HDU - 3308 这个是一个很简单很明显的线段树的区间合并,不过区间合并的题目都还是有点难写,建议存个板子. #include <cstdio> #include & ...
- [HDOJ3308]LCIS(线段树,区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题意:给定n个数,两个操作: U A B:将位置A的数值改成B Q A B:查询[A,B]内最长 ...
- HDU-3308 LCIS(区间合并)
题目大意:给一个整数序列,m次询问,每次询问某个区间中最长连续上升子序列的长度. 题目分析:线段树区间合并.维护以区间左端开头的.以区间右端点结尾的和区间最长的上升连续序列. 代码如下: # incl ...
随机推荐
- 最详细的PHP flush()与ob_flush()的区别详解
buffer ---- flush()buffer是一个内存地址空间,Linux系统默认大小一般为4096(1kb),即一个内存页.主要用于存储速度不同步的设备或者优先级不同的 设备之间传办理数据的区 ...
- Canvas+Video打造酷炫播放体验
一.简介 直到现在,仍然不存在一项旨在网页上显示视频的标准. 今天,大多数视频是通过插件(比如 Flash)来显示的.然而,并非所有浏览器都拥有同样的插件. HTML5 规定了一种通过 video 元 ...
- 详解 HTTPS 移动端对称加密套件优
近几年,Google.Baidu.Facebook 等互联网巨头大力推行 HTTPS,国内外的大型互联网公司很多也都已启用全站 HTTPS. Google 也推出了针对移动端优化的新型加密套件 Cha ...
- 第6章 Overlapped I/O, 在你身后变戏法 ---1
这一章描述如何使用 overlapped I/O(也就是 asynchronous I/O).某些时候 overlapped I/O 可以取代多线程的功用.然而,overlapped I/O 加上co ...
- 快速双边滤波 附完整C代码
很早之前写过<双边滤波算法的简易实现bilateralFilter>. 当时学习参考的代码来自cuda的样例. 相关代码可以参阅: https://github.com/johng12/c ...
- hdu3729二分匹配
I'm Telling the Truth Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- Day4 闭包、装饰器decorator、迭代器与生成器、面向过程编程、三元表达式、列表解析与生成器表达式、序列化与反序列化
一.装饰器 一.装饰器的知识储备 1.可变长参数 :*args和**kwargs def index(name,age): print(name,age) def wrapper(*args,**k ...
- spring 内部工作机制(一)
Spring内部机制的内容较多,所以打算多分几个阶段来写. 本章仅探索Spring容器启动做了哪些事: 前言: 都说Spring容器就像一台构造精妙的机器,此话一点不假,我们通过配置文件向机器传达控制 ...
- html5获取用户当前的地理位置,即经纬度。
$("document").ready(function(){ getMap(); }); function getMap(){ // 百度地图API功能 var map = ne ...
- JAVA提高一:静态导入、可变参数、增强型for循环、装拆箱
国庆假期已结束,假期8天,全部在家带娃,体会到了妻子的不容易,需要好好努力来多赚钱了,言归正传.10月份开始进去JAVA 高级语法知识学习,本节复习学习的为:静态导入.可变参数.增强型for循环.装拆 ...