1. 程式人生 > >HDU - 3308 LCIS 單點更新區間查詢

HDU - 3308 LCIS 單點更新區間查詢

題解: 單點更新 區間查詢 分別儲存左連續 右連續 區間最大值  區間左右端點的大小 合併的時候判斷大小關係即可

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<=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
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int n,m;
struct node
{
    int l,r;
    int ml,mr,mx;
    int numl,numr;
}tree[maxn<<2];
void pushup(int cur)
{
    tree[cur].numl=tree[cur*2].numl;
    tree[cur].numr=tree[cur*2+1].numr;
    tree[cur].mx=max(tree[cur*2].mx,tree[cur*2+1].mx);
    if(tree[cur*2].numr<tree[cur*2+1].numl)
        tree[cur].mx=max(tree[cur].mx,tree[cur*2].mr+tree[cur*2+1].ml);
    tree[cur].ml=tree[cur*2].ml;
    if(tree[cur].ml==tree[cur*2].r-tree[cur*2].l+1&&tree[cur*2].numr<tree[cur*2+1].numl)
        tree[cur].ml+=tree[cur*2+1].ml;
    tree[cur].mr=tree[cur*2+1].mr;
    if(tree[cur].mr==tree[cur*2+1].r-tree[cur*2+1].l+1&&tree[cur*2].numr<tree[cur*2+1].numl)
        tree[cur].mr+=tree[cur*2].mr;
}
void build(int l,int r,int cur)
{
    tree[cur].l=l;
    tree[cur].r=r;

    if(r==l)
    {
        scanf("%d",&tree[cur].numl);
        tree[cur].numr=tree[cur].numl;
        tree[cur].ml=tree[cur].mr=tree[cur].mx=1;
        return;
    }
    int mid=(r+l)>>1;
    build(l,mid,cur<<1);
    build(mid+1,r,cur<<1|1);
    pushup(cur);
    //printf("%d-%d %d \n",tree[cur].l,tree[cur].r,tree[cur].mx);
}
int query(int pl,int pr,int cur)
{
    if(pl<=tree[cur].l&&tree[cur].r<= pr)
    {
        return tree[cur].mx;
    }
    int res=0;
    if(pl<=tree[cur*2].r) res=max(res,query(pl,pr,cur*2));
    if(pr>=tree[cur*2+1].l) res=max(res,query(pl,pr,cur*2+1));
    if(pl<=tree[cur*2].r&&pr>=tree[cur*2+1].l&&tree[cur*2].numr<tree[cur*2+1].numl)//
        res=max(res,min(tree[cur*2].mr,tree[cur*2].r-pl+1)+min(tree[cur*2+1].ml,pr-tree[cur*2+1].l+1));
    return res;
}
void update(int cur,int tar,int x)
{
    if(tree[cur].l==tree[cur].r)
    {
        tree[cur].numl=tree[cur].numr=x;
        return;
    }
    if(tar<=tree[cur*2].r) update(cur<<1,tar ,x);
    else update(cur<<1|1,tar ,x);
    pushup(cur);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        build(0,n-1,1);
        while(m--)
        {
            char op[2];
            int l,r;
            int tar,x;
            scanf("%s",op);
            if(op[0]=='Q')
            {
                scanf("%d%d",&l,&r);
                printf("%d\n",query(l,r,1));
            }
            else
            {
                scanf("%d%d",&tar,&x);
                update(1,tar,x);
            }
        }
    }
	return 0;
}