LCIS
傳送門1
傳送門2
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 .
Input
in the first line, indicating the case number.
Each case starts with two integers .
The next line has n integers .
The next m lines each has an operation:
U A B
OR
Q A B .
Output
For each , 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
題意
找最長上升子串(區間).
分析
線段樹區間合併.
注意到在 中的LCIS,可能在左兒子,可能在右兒子,還可能跨越左右.
跨越左右的即爲左兒子最長上升後綴+右兒子最長上升前綴.故線段樹需維護三個量:最長上升前後綴與子串(區間).
對於每個節點,
Tree[p].lmx>=Tree[p<<1].lmx,
Tree[p].rmx>=Tree[p<<1|1].rmx,
Tree[p].mx >=max(Tree[p<<1].mx,Tree[p<<1|1].mx
另外,若左兒子最右邊的數<右兒子左邊的數,則左後綴與右前綴之和爲一個待選項.此時左後綴與右前綴也有另外的待選項.
CODE
#include<iostream>
#include<cstdio>
#define FOR(i,a,b) for(int i=(a),i##_END_=(b);i<=i##_END_;i++)
#define Lson l,mid,p<<1
#define Rson mid+1,r,p<<1|1
#define N 100005
using namespace std;
void Rd(int &x) {
char c;x=0;
while((c=getchar())<48);
do x=(x<<1)+(x<<3)+(c^48);
while((c=getchar())>47);
}
int n,m;
int A[N];
struct SegT {int mx,lmx,rmx;} Tree[N<<2];
void Up(int l,int r,int p){
int len=r-l+1,mid=(l+r)>>1;
Tree[p].lmx=Tree[p<<1].lmx;
Tree[p].rmx=Tree[p<<1|1].rmx;
Tree[p].mx=max(Tree[p<<1].mx,Tree[p<<1|1].mx);
if(A[mid]<A[mid+1]){
if(Tree[p].rmx==(len>>1))Tree[p].rmx+=Tree[p<<1].rmx;
if(Tree[p].lmx==len-(len>>1))Tree[p].lmx+=Tree[p<<1|1].lmx;
Tree[p].mx=max(Tree[p].mx,Tree[p<<1].rmx+Tree[p<<1|1].lmx);
}
}
int Query(int l,int r,int nl,int nr,int p) {
if(l>=nl&&r<=nr)return Tree[p].mx;
int Mx=1,mid=(l+r)>>1;
if(nl<=mid) Mx=Query(l,mid,nl,nr,p<<1);
if(nr>=mid+1) Mx=max(Mx,Query(mid+1,r,nl,nr,p<<1|1));
if(A[mid]<A[mid+1])
Mx=max(Mx,min(mid-nl+1,Tree[p<<1].rmx)+min(nr-mid,Tree[p<<1|1].lmx));
return Mx;
}
void Build(int l,int r,int p){
if(l==r){
Tree[p].mx=Tree[p].lmx=Tree[p].rmx=1;
return;
}
int mid=(l+r)>>1;
Build(Lson),Build(Rson);
Up(l,r,p);
}
void Update(int l,int r,int x,int k,int p){
if(l==r){
A[l]=k;
return;
}
int mid=(l+r)>>1;
if(x<=mid)Update(l,mid,x,k,p<<1);
else Update(mid+1,r,x,k,p<<1|1);
Up(l,r,p);
}
int main() {
int T,a,b;
char chr[2];
scanf("%d",&T);
while(T--) {
scanf("%d %d",&n,&m);
FOR(i,1,n)Rd(A[i]);
Build(1,n,1);
while(m--) {
scanf("%s",chr);
Rd(a),Rd(b);
if(chr[0]=='Q') printf("%d\n",Query(1,n,a+1,b+1,1));
else Update(1,n,a+1,b,1);
}
}
return 0;
}