题意:
U X Y : 更新X位置为Y
Q X Y : 查询【X,Y】区间的最长连续严格上升序列的长度
思路:
本题做区间合并有四种情况:
1.只有左区间在【X,Y】中
2.只有右区间在【X,Y】中
3.左右区间都在【X,Y】中,但合并后,左区间的右端点和右区间的左端点结合不能产生新的连续段
4.左右区间都在【X,Y】中,合并后,左区间的右端点和右区间的左端点结合能产生新的连续段
显然,其中一二种情况不用合并,父区间的长度就是左或右节点的长度。第三种情况父区间的长度就是左和右节点的长度的最大者。
而对于第四种情况我们需要知道左右区间合并后产生的新的连续段的长度是多少。父区间的长度就是左节点和右节点以及新连续段三者中的最大者。
所以我们需要知道一个区间,从最左端的开始的连续序列长度和最右端的开始的连续序列长度。
新合成的连续段就是左区间右端连续序列长度+右区间左端连续序列长度
综上:我们需要维护的值有三:
区间的最大连续长度
从区间最左端开始的最大连续长度
从区间最右端开始的最大连续长度
代码:
#include <bits/stdc++.h>
using namespace std;
#define lson rt<<1,l,mid
#define rson (rt<<1)|1,mid+1,r
#define mi (l+r)>>1
#define ls rt<<1
#define rs (rt<<1)|1
int st,en;
const int MAXN=1e5+100;
int lsum[MAXN*4];
int rsum[MAXN*4];
int sum[MAXN*4];
int a[MAXN];
void push_up(int rt,int l,int r){
lsum[rt]=lsum[ls];
rsum[rt]=rsum[rs];
sum[rt]=max(sum[ls],sum[rs]);
int mid=mi;
int len=r-l+1;
int rlen=len/2;
int llen=len-rlen;
int conbine=0;
if(a[mid]<a[mid+1]){
if(lsum[rt]==llen) lsum[rt]+=lsum[rs];
if(rsum[rt]==rlen) rsum[rt]+=rsum[ls];
conbine=rsum[ls]+lsum[rs];
}
sum[rt]=max(sum[rt],conbine);
return ;
}
void build(int rt,int l,int r){
if(l==r){
sum[rt]=lsum[rt]=rsum[rt]=1;
return ;
}
int mid=mi;
build(lson);
build(rson);
push_up(rt,l,r);
return ;
}
void update(int rt,int l,int r){
if(l==r){
return;
}
int mid=mi;
if(st<=mid)
update(lson);
if(mid<st)
update(rson);
push_up(rt,l,r);
return ;
}
int query(int rt,int l,int r){
if(st<=l&&r<=en){
return sum[rt];
}
int mid=mi;
int ans;
if(en<=mid)
ans=query(lson);
else if(mid<st)
ans=query(rson);
else{
int ans1=query(lson);
int ans2=query(rson);
ans=max(ans1,ans2);
int conbine=0;
if(a[mid]<a[mid+1]) conbine=min(rsum[ls],mid-st+1)+min(lsum[rs],en-mid);
ans=max(ans,conbine);
}
return ans;
}
int main(){
int T,n,m;
char ch[2];
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
int ans;
for(int i=0;i<m;i++){
scanf("%s%d%d",ch,&st,&en);
if(ch[0]=='U'){
st++;
a[st]=en;
update(1,1,n);
}else{
st++;en++;
ans=query(1,1,n);
printf("%d\n",ans);
}
}
}
return 0;
}
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].
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<=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).
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).
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