HDU3308 LCIS(線段樹區間合併)

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 [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) .

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


題意

找最長上升子串(區間).

分析

線段樹區間合併.
注意到在[l,r] 中的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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章