hdu3308LCIS(线段树,点更新,段查寻,查寻时一定要注意跨越时如何计算)
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<=10
5).
The next line has n integers(0<=val<=10
5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10
5)
OR
Q A B(0<=A<=B< n).
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
1
4
2
3
1
2
5
1. 左儿子最右边的值 < 右儿子最左边的值 lMax = (左儿子的lMax == 左儿子的len) ? 左儿子的len + 右儿子的lMax : 左儿子的lMax;
rMax = (右儿子的rMax == 右儿子的len) ? 右儿子的len + 左儿子的rMax : 右儿子的rMax;
Max = MAX(左儿子的rMax + 右儿子的lMax, 左儿子的Max, 右儿子的Max, lMax, rMax); 2. 左儿子最右边的值 >= 右儿子最左边的值
lMax = 左儿子的lMax;
rMax = 右儿子的rMax;
Max = MAX(左儿子的Max, 右儿子的Max);
注意:在查寻时,当跨越左右子树时则一这要注意这个,当 左节点的最右边的值< 右节点的最左边的值时,那么有可能最长升序在这时最大,并且不能超过这个范围。
#include<stdio.h>
#define N 500010
struct node
{
int Llcis,Rlcis,lcis;//最左连续升序长度,最右连续升序长度,这个范围的最长连续升序长度
}tree[8*N];
int num[N+5];
int max(int a,int b){ return a>b?a:b;}
void chang_tree(int l,int r,int k)//根据第K个节点的左右节点,计算第K个节点的最左,最右和最长 的升序长度
{
int m=(l+r)/2;
node ltree=tree[k*2],rtree=tree[k*2+1];
if(num[m]>=num[m+1])//当左节点的最右边的值不小右节点的最左边的值时
{
tree[k].Llcis=ltree.Llcis;
tree[k].Rlcis=rtree.Rlcis;
tree[k].lcis=max(ltree.lcis,rtree.lcis);
}
else
{
if(m-l+1==ltree.Llcis) tree[k].Llcis=ltree.Llcis+rtree.Llcis;
else tree[k].Llcis=ltree.Llcis;
if(r-m==rtree.Rlcis) tree[k].Rlcis=rtree.Rlcis+ltree.Rlcis;
else tree[k].Rlcis=rtree.Rlcis;
tree[k].lcis=max(ltree.lcis,ltree.Rlcis+rtree.Llcis);
tree[k].lcis=max(tree[k].lcis,rtree.lcis);
tree[k].lcis=max(tree[k].lcis,tree[k].Llcis);
tree[k].lcis=max(tree[k].lcis,tree[k].Rlcis);
}
}
void build(int l,int r,int k)
{
int m=(l+r)/2;
if(l==r){
tree[k].Llcis=1;
tree[k].lcis=1;
tree[k].Rlcis=1;
return ;
}
build(l,m,k*2);
build(m+1,r,k*2+1);
chang_tree(l,r,k);
}
void updata(int l,int r,int k,int Q,int ans)
{
int m=(l+r)/2;
if(l==Q&&Q==r)
{num[Q]=ans; return ;}
if(Q<=m) updata(l,m,k*2,Q,ans);
if(Q>m) updata(m+1,r,k*2+1,Q,ans);
chang_tree(l,r,k);
}
int maxlen;
void find(int l,int r,int k,int L,int R)
{
int m=(l+r)/2;
if(L<=l&&r<=R){
maxlen=max(tree[k].lcis,maxlen);
return ;
}
if(R<=m) find(l,m,k*2,L,R);
else if(L>m) find(m+1,r,k*2+1,L,R);
else{
find(l,m,k*2,L,R);
find(m+1,r,k*2+1,L,R);
//-----当查寻夸越左右子树时,左子树的最右端点的值小于右子树的最左端点的值------
if(num[m]<num[m+1])
if(L<=m-tree[2*k].Rlcis+1&&m+tree[k*2+1].Llcis<=R)//注意这个条件
maxlen=max(tree[k*2].Rlcis+tree[k*2+1].Llcis,maxlen);
else if(L<=m-tree[2*k].Rlcis+1&&m+tree[k*2+1].Llcis>R)//注意这个条件
maxlen=max(tree[k*2].Rlcis+R-m,maxlen);
else if(L>m-tree[2*k].Rlcis+1&&m+tree[k*2+1].Llcis<=R)//注意这个条件
maxlen=max(m-L+1+tree[k*2+1].Llcis,maxlen);
else maxlen=R-L+1;//最长的升序长度
}
}
int main()
{
int t,n,m,QL,QR;
char c[2];
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
build(1,n,1);
while(m--)
{
scanf("%s%d%d",c,&QL,&QR);
if(c[0]=='U') updata(1,n,1,QL+1,QR);
if(c[0]=='Q')
{
maxlen=0; find(1,n,1,QL+1,QR+1);
printf("%d\n",maxlen);
}
}
}
}
hdu3308LCIS(线段树,点更新,段查寻,查寻时一定要注意跨越时如何计算)的更多相关文章
- Codeforces295A - Greg and Array(线段树的成段更新)
题目大意 给定一个序列a[1],a[2]--a[n] 接下来给出m种操作,每种操作是以下形式的: l r d 表示把区间[l,r]内的每一个数都加上一个值d 之后有k个操作,每个操作是以下形式的: x ...
- LCIS线段树(区间更新)
首先线段树每一个节点包含:[b,e],lmax,rmax,max;其中lmax表示从左端点开始连续的最长的增序列长度,rmax表示从e端点开始向左连续的最长下降序列长度,max表示当前区间的连续递增的 ...
- ZOJ 1610 Count the Colors (线段树区间更新)
题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头 ...
- HDU 3577 Fast Arrangement (线段树区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3577 题意不好理解,给你数字k表示这里车最多同时坐k个人,然后有q个询问,每个询问是每个人的上车和下车 ...
- zoj 1610 Count the Colors(线段树延迟更新)
所谓的懒操作模板题. 学好acm,英语很重要.做题的时候看不明白题目的意思,我还拉着队友一块儿帮忙分析题意.最后确定了是线段树延迟更新果题.我就欣欣然上手敲了出来. 然后是漫长的段错误.... 第一次 ...
- HDU 1166 敌兵布阵(线段树单点更新,板子题)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- UESTC 1591 An easy problem A【线段树点更新裸题】
An easy problem A Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others ...
- hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)
#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题 ...
- ZOJ 1610 Count the Color(线段树区间更新)
描述Painting some colored segments on a line, some previously painted segments may be covered by some ...
- HDU 1166 敌兵布阵(线段树单点更新,区间查询)
描述 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况 ...
随机推荐
- (转)JS的parent对象
---http://blog.sina.com.cn/s/blog_a15aa5690101a5yz.html top:该变更永远指分割窗口最高层次的浏览器窗口.如果计划从分割窗口的最高层次开始执行命 ...
- iOS-点击视图,视图背景颜色随机更改
一.效果图 二.代码 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the v ...
- java面试题及答案(基础题122道,代码题19道)
JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分, ...
- excel设置单元格不可编辑
把允许编辑的单元格选定,右键-设置单元格格式-保护,把锁定前的对钩去掉.再点工具-保护工作表.这样就可以只让你刚才设定的单元格允许编辑,其他不允许.
- javascript 字符串滚动显示
<html> <head> <script type="text/javascript"> var chars = "JavaScri ...
- CSS hack技巧
CSS hack技巧一览,原文来自CSDN freshlover的博客专栏<史上最全CSS Hack方式一览> 什么是CSS hack 由于不同厂商的流览器或某浏览器的不同版本(如IE6- ...
- IPv6-only 的兼容性解决方案-b
前几天Apple宣布 6月1日后所有应用必须支持IPv6-only网络 今天抽空看了下这方面的知识 首先解释下IPv6的是什么? 维基百科的定义如下:IPv6是Internet Protocol ve ...
- Python三元表达式
我们知道Python没有三元表达式,但是我们通过技巧达到三元表达式的效果. 摘自<Dive Into Python>: 在Python 中,and 和 or 执行布尔逻辑演算,如你所期待的 ...
- Web分析日志分析2
http://www.docin.com/p-649515490.html http://wenku.baidu.com/link?url=kB-83fbl1Zc3Y6U2BYLj-lKMWShe8Z ...
- zoj 3785 What day is that day?
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5272 打表找规律. #include <cstdio> #incl ...