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 <= 10 5 ) .
The next line has n integers ( 0 <= v a l <= 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


题意

找最长上升子串(区间).

分析

线段树区间合并.
注意到在 [ 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;
}
发布了34 篇原创文章 · 获赞 44 · 访问量 5063

猜你喜欢

转载自blog.csdn.net/zzyyyl/article/details/82693424
今日推荐