hdu 3308 LCIS

最近开始线段树一段时间了,也发现了不少大牛的博客比如HH大牛  ,小媛姐。这个题目是我在看HH大牛的线段树专题是给出的习题,(可以去他博客找找,真心推荐)原本例题是POJ3667 Hotel  这个题目,是一个求连续空区间的情况,而hdoj这个题目是求给定区间单调连续的最大区间长度,两个题目思路很相似,将节点rt用sum[rt],lsum[rt],rsum[rt]来描述,分别表示rt对应区间即[l,r]内满足条件的区间的最大长度,从左边端点l开始满足条件的最大区间长度,从右边r开始向左的满足条件的最大区间长度。

void PushUp(int rt,int m,int mid)//mid表示更新区间的中点,m表示长度
{
    lsum[rt]=lsum[rt<<1];
    rsum[rt]=rsum[rt<<1|1];
    int t=1;
    if(A[mid]<A[mid+1])
    {
        if(lsum[rt]==(m-(m>>1)))
            lsum[rt]+=lsum[rt<<1|1];
        if(rsum[rt]==(m>>1))
            rsum[rt]+=rsum[rt<<1];
        t= rsum[rt<<1]+lsum[rt<<1|1];
    }
       sum[rt]=max(t,max(sum[rt<<1],sum[rt<<1|1]));
}

PushUp函数和query函数是关键  ,PushUp函数向上更新时,先将lsum[rt]用

lsum[rt<<1]也就是左子区间左边开始的最大长度,如果这个区间长度刚好是l到mid之间的长度,说明区间已经穿过中点了,应该在加上右子区间lsum[rt<<1|1]这部分,类似的可以更新rsum[rt]。对于sum[rt]应该对应rsum[rt<<1]+lsum[rt<<1|1],sum[rt<<1],sum[rt<<1|1]三种情况中的最大值,因为满足条件的最长单调区间可以是左半部分,右半部分,或者贯穿中点。

理解了这部分那么query函数可以按照类似的思路来写,但要注意的是对于贯穿中点的判断条件是A[mid]<A[mid+1],这样才能将两部分加起来。

期间又一次犯二TLE了,原本是用C写的,max函数是用的宏定义,结果里面含有query函数,这样最终可能会两次调用query函数,不超时才怪,好在以前犯过一次,被基友发现了,改成algorithm里面的max就过了。哎,有个能debug基友就是好啊。hhha。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define N 100010
  5 #define lson l,m,rt<<1
  6 #define rson m+1,r,rt<<1|1
  7 
  8 using namespace std;
  9 int sum[N<<2],rsum[N<<2],lsum[N<<2],A[N];
 10 
 11 void PushUp(int rt,int m,int mid)
 12 {
 13     lsum[rt]=lsum[rt<<1];
 14     rsum[rt]=rsum[rt<<1|1];
 15     int t=1;
 16     if(A[mid]<A[mid+1])
 17     {
 18         if(lsum[rt]==(m-(m>>1)))
 19             lsum[rt]+=lsum[rt<<1|1];
 20         if(rsum[rt]==(m>>1))
 21             rsum[rt]+=rsum[rt<<1];
 22         t= rsum[rt<<1]+lsum[rt<<1|1];
 23     }
 24        sum[rt]=max(t,max(sum[rt<<1],sum[rt<<1|1]));
 25 }
 26 
 27 void build(int l,int r,int rt)
 28 {
 29     if(l==r)
 30     {
 31         sum[rt]=lsum[rt]=rsum[rt]=1;
 32         return;
 33     }
 34     int m=(l+r)>>1;
 35     build(lson);
 36     build(rson);
 37     PushUp(rt,r-l+1,m);
 38 }
 39 
 40 void update(int p,int l,int r,int rt)
 41 {
 42     if(l==r)
 43         return;
 44     int m=(l+r)>>1;
 45     if(p<=m)
 46         update(p,lson);
 47     else update(p,rson);
 48     PushUp(rt,r-l+1,m);
 49 }
 50 
 51 int query(int L,int R,int l,int r,int rt)
 52 {
 53     if(L<=l&&R>=r)
 54     {
 55         return sum[rt];
 56     }
 57     int m=(l+r)>>1;
 58     if(l==r)
 59         return 1;
 60     int ans=0;
 61     if(R<=m)
 62         ans=max(ans,query(L,R,lson));
 63     else  if(L>m)
 64         ans=max(ans,query(L,R,rson));
 65     else
 66     {
 67         ans=max(ans,query(L,R,lson));
 68         ans=max(ans,query(L,R,rson));
 69         int ll,rr;
 70         if(m-L+1>=rsum[rt<<1])
 71             ll=rsum[rt<<1];
 72         else ll=m-L+1;
 73         if(R-m>=lsum[rt<<1|1])
 74             rr=lsum[rt<<1|1];
 75         else rr=R-m;
 76         ans=max(ans,ll);
 77         ans=max(ans,rr);
 78         if(A[m+1]>A[m])
 79             ans=max(ans,ll+rr);
 80     }
 81     return ans;
 82 }
 83 
 84 int main(void)
 85 {
 86     int T;
 87     int n,m,a,b;
 88     char op[3];
 89     scanf("%d",&T);
 90     while(T--)
 91     {
 92         scanf("%d%d",&n,&m);
 93         for(int i=1; i<=n; i++)
 94             scanf("%d",A+i);
 95         build(1,n,1);
 96         while(m--)
 97         {
 98             scanf("%s%d%d",op,&a,&b);
 99             if(op[0]=='U')
100             {
101                 A[a+1]=b;
102                 update(a+1,1,n,1);
103             }
104             else
105             {
106                 int ans=query(a+1,b+1,1,n,1);
107                 printf("%d\n",ans);
108             }
109         }
110     }
111     return 0;
112 }

 

posted on 2013-08-10 22:31  rootial  阅读(516)  评论(0编辑  收藏  举报

导航