hdu 3308 LCIS(线段树区间合并)

来源:互联网 发布:php魔术方法作用 编辑:程序博客网 时间:2024/05/04 14:05

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308

LCIS

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5792    Accepted Submission(s): 2513


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].
 

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
110 107 7 3 3 5 9 9 8 1 8 Q 6 6U 3 4Q 0 1Q 0 5Q 4 7Q 3 5Q 0 2Q 4 6U 6 10Q 0 9
 

Sample Output
11423125
 

Author
shǎ崽
 

Source
HDOJ Monthly Contest – 2010.02.06
 

Recommend
wxl   |   We have carefully selected several similar problems for you:  3397 1542 1828 2871 1255 
 

题目大意:给n个数,m个操作。两种操作:Q a b 表示查询【a,b】这个区间的LCIS(即最长连续递增子序列)的长度。U a b 表示更新第a个数把他变成b(从0开始)。

解题思路:主要解决简单的单点更新和区间的查询,区间记录最长的连续递增子序列长度。要分析清楚各种情况。

详见代码。
#include <iostream>#include <cstdio>using namespace std;struct node{    int l,r;    int mmax;    int lmax,rmax;    int lnum,rnum;}s[100000*4+10];void InitTree(int l,int r,int k){    s[k].l=l;    s[k].r=r;    s[k].mmax=1;    s[k].rmax=1;    s[k].lmax=1;    s[k].lnum=s[k].rnum=0;    if (l==r)        return ;    int mid=(l+r)/2;    InitTree(l,mid,2*k);    InitTree(mid+1,r,2*k+1);}void UpdataTree(int i,int change,int k){    if (s[k].l==s[k].r&&s[k].l==i)    {        s[k].lnum=s[k].rnum=change;        return ;    }    int mid=(s[k].l+s[k].r)/2;    if (i>mid)        UpdataTree(i,change,2*k+1);    else if (i<=mid)        UpdataTree(i,change,2*k);    s[k].lnum=s[k*2].lnum;    s[k].rnum=s[k*2+1].rnum;    s[k].lmax=s[k*2].lmax;    s[k].rmax=s[k*2+1].rmax;    s[k].mmax=max(s[k*2].mmax,s[k*2+1].mmax);    if(s[k*2].rnum<s[k*2+1].lnum)    {        s[k].mmax=max(s[k].mmax,s[k*2].rmax+s[k*2+1].lmax);        if(s[k*2].lmax==s[k*2].r-s[k*2].l+1)            s[k].lmax=s[k*2].lmax+s[k*2+1].lmax;        if(s[k*2+1].rmax==s[k*2+1].r-s[k*2+1].l+1)            s[k].rmax=s[k*2].rmax+s[k*2+1].rmax;    }}int SearchTree(int l,int r,int k){    if (s[k].l==l&&s[k].r==r)        return s[k].mmax;    else    {        int mid=(s[k].l+s[k].r)/2;        if (l>mid)            return SearchTree(l,r,2*k+1);        else if (r<=mid)            return SearchTree(l,r,2*k);        /*else        {            if (s[k].lnum<s[k].rnum)                return SearchTree(l,mid,2*k)+SearchTree(mid+1,r,2*k+1);            else if        }*/        else        {            int a=min(s[k*2].rmax,mid-l+1);            int b=min(s[k*2+1].lmax,r-mid);            int Max=max(a,b);            Max=max(Max,SearchTree(l,mid,2*k));            Max=max(Max,SearchTree(mid+1,r,2*k+1));            if(s[k*2].rnum<s[2*k+1].lnum)            {                Max=max(Max,a+b);            }            return Max;        }    }}int main(){    int t;    char ch[70];    scanf("%d",&t);    while (t--)    {        int n,m,w,a,b;        scanf("%d%d",&n,&m);        InitTree(0,n-1,1);        for (int i=0; i<n; i++)        {            scanf("%d",&w);            UpdataTree(i,w,1);        }        for (int i=0; i<m; i++)        {            //getchar();            scanf("%s%d%d",ch,&a,&b);            if (ch[0]=='Q')            {                //cout<<"!!!!!!!!!!!!!!!!!"<<endl;                int ans=SearchTree(a,b,1);                printf ("%d\n",ans);            }            else if (ch[0]=='U')            {                UpdataTree(a,b,1);            }        }    }    return 0;}



1 0
原创粉丝点击