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的任务就是要监视这些工兵营地的活动情况 ...
随机推荐
- javascript判断值是否undefined
function isUndefined(variable) { return typeof variable == 'undefined' ? true : false; }
- iOS开发之字典数据建立模型步骤
1. 在控制器属性的(questions)set方法中完成字典转模型的操作 - (NSArray *)questions { if (nil == _questions) { //1.加载plist文 ...
- cxf框架使用(一)
1.创建调用接口 @WebService public interface IQueryBusinessService { public @WebResult(name="QueryBusi ...
- os mac apache+php+mysql环境配置
1.启用系统自带的apache 服务 打开终端(terminal) #sudo apachectl start #sudo vi /etc/apache2/httpd.conf 修改 LoadModu ...
- php 带cookie采集某页面
<?php error_reporting(0); define("temp_dir", dirname(__FILE__)."/Public/"); d ...
- indexof()方法
w3c手册定义和用法 indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置 stringObject.indexOf(searchvalue,fromindex) searchva ...
- Sample rate 理解
在Gnuradio中,我们可以看到很多模块中都有Sample rate 这个概念 然后看到一个说明 Any processing block's 'Sample Rate' parameter is ...
- 使用飞信api接口实现短信发送(只能发送好友)
找了很久才找到一个能用的飞信API接口(http://quanapi.sinaapp.com/fetion.php?u=飞信登录手机号&p=飞信登录密码&to=接收飞信的手机号& ...
- .NET MVC插件化开发框架源码(插件功能完善版)
离上次第一次上传源码一个多星期了,在工作之余今天终于把插件管理部门的功能全部完善了,已可用于实际开发,管理界面因为没人帮忙设计,所以有点丑,今天这版算是0.1.0.0吧,后面我会发布很多插件来填充这个 ...
- codevs 4310 复制书稿
4310 复制书稿 时间限制: 1 s 空间限制: 4000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 现在要把m本有顺序的书分给k个人 ...