hdu3308 LCIS
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].
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).
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
这题属于线段树区间合并,题意是求一个区间内的最长连续递增子序列。首先用线段树维护7个节点,l,r,llen,rlen,tlen,lnum,rnum;(llen,rlen表示这段区间从最左(右)向右(左)可以持续的最大递增子序列长度。tlen表示这条线段的最大递增子序列长度,lnum,rnum表示这段线段最左边和左右边的值)。我在一开始建树的时候就把7个初始化好了,这样下面就比较方便。
这里的难点是查询,当查询区间全落在左子树或者右子树的时候比较简单,直接算子树的最大长度,但落在中间的时候要考虑合并的值,这里合并时注意不能直接用b[i*2].rlen+b[i*2+1].llen,因为查询的区间(l,r)可能大于b[2*i+1].l+b[2*i+1].llen-1或者小于b[2*i].r-b[2*i].rlen+1,这样就要分类讨论。这里卡了很长时间= =。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
int a[100005],num;
char s[10];
struct node{
int l,r,llen,rlen,tlen,lnum,rnum;
}b[8*100005];
int max(int a,int b){
return a>b?a:b;
}
void build(int l,int r,int i)
{
int mid;
b[i].l=l;b[i].r=r;
if(l==r){
b[i].lnum=b[i].rnum=a[l];
b[i].rlen=b[i].llen=b[i].tlen=1;
return;
}
mid=(l+r)/2;
build(l,mid,i*2);
build(mid+1,r,i*2+1);
b[i].lnum=b[i*2].lnum;
b[i].rnum=b[i*2+1].rnum;
b[i].tlen=max(b[i*2].tlen,b[i*2+1].tlen);
if(b[i*2].rnum<b[i*2+1].lnum){
b[i].tlen=max(b[i].tlen,b[i*2].rlen+b[i*2+1].llen);
}
b[i].llen=b[i*2].llen;
if(b[i*2].rnum<b[i*2+1].lnum && b[i*2].llen==(b[i*2].r-b[i*2].l+1)){
b[i].llen+=b[i*2+1].llen;
}
b[i].rlen=b[i*2+1].rlen;
if(b[i*2].rnum<b[i*2+1].lnum && b[i*2+1].rlen==(b[i*2+1].r-b[i*2+1].l+1)){
b[i].rlen+=b[i*2].rlen;
}
}
void update(int index,int num,int i)
{
int mid;
if(b[i].l==b[i].r){
b[i].rnum=b[i].lnum=num;return;
}
if(b[i*2].r-b[i*2].l+1>=index)update(index,num,i*2);
else update(index-(b[i*2].r-b[i*2].l+1),num,i*2+1);
b[i].lnum=b[i*2].lnum;
b[i].rnum=b[i*2+1].rnum;
b[i].tlen=max(b[i*2].tlen,b[i*2+1].tlen);
if(b[i*2].rnum<b[i*2+1].lnum){
b[i].tlen=max(b[i].tlen,b[i*2].rlen+b[i*2+1].llen);
}
b[i].llen=b[i*2].llen;
if(b[i*2].rnum<b[i*2+1].lnum && b[i*2].llen==(b[i*2].r-b[i*2].l+1)){
b[i].llen+=b[i*2+1].llen;
}
b[i].rlen=b[i*2+1].rlen;
if(b[i*2].rnum<b[i*2+1].lnum && b[i*2+1].rlen==(b[i*2+1].r-b[i*2+1].l+1)){
b[i].rlen+=b[i*2].rlen;
}
}
void question(int l,int r,int i)
{
int mid,r1,l1;
if(b[i].l==l && b[i].r==r){
num=max(num,b[i].tlen);return;
}
mid=(b[i].l+b[i].r)/2;
if(r<=mid)question(l,r,i*2);
else if(l>mid)question(l,r,i*2+1);
else if(l<=mid && r>mid){
if(b[i*2].rnum<b[i*2+1].lnum){
if(b[2*i+1].l+b[2*i+1].llen-1>=r)r1=r;
else r1=b[2*i+1].l+b[2*i+1].llen-1;
if(b[2*i].r-b[2*i].rlen+1<=l)l1=l;
else l1=b[2*i].r-b[2*i].rlen+1;
num=max(num,r1-l1+1);
}
question(l,mid,i*2);
question(mid+1,r,i*2+1);
}
}
int main()
{
int n,m,i,j,T,c,d;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,n,1);
for(i=1;i<=m;i++){
scanf("%s",s);
if(s[0]=='Q'){
scanf("%d%d",&c,&d);
num=0;
question(c+1,d+1,1);
printf("%d\n",num);
}
else if(s[0]=='U'){
scanf("%d%d",&c,&d);
update(c+1,d,1);
}
}
}
return 0;
}