poj 1823 Hotel 线段树

来源:互联网 发布:大津算法 matlab 编辑:程序博客网 时间:2024/06/05 09:46
这个题目意思很简单,就是求连续的最长段。
查询次数比较多,时间卡的比较紧
之前写了个k*logn*logn的,结果tle了,pushup的时候如果每次都修改到满节点时pushup的话,因为一个区间最多被分成logn次,加上每次pushup最多执行logn次操作,所以复杂度就高了
其实更简单一点的方法是当修改了一个节点的局部时,就重新修改该节点的值。这样复杂度就变低了,这样看起来,真的还是得多思考,线段树貌似多种修改都是采取后面的方法会快得多。

讲讲具体思路: 非常简单,lamx,rmax,max分别表示左连续最大,右连续最大,连续最大。
             修改的时候注意维护好树就可以了。
                        
#include <iostream>
#include <stdio.h>
#include <string.h>
#define ls t<<1
#define rs t<<1|1
#define midt(tr[t].l+tr[t].r)>>1
using namespace std;
const int maxn=16000+10;

struct
{
    int l,r;
    int max,lmax,rmax;
    int lazy;
}tr[maxn*4];

inline int max(int a,int b)
{
    if(a>b)return(a);
    return(b);
}

int maketree(int t,int l,int r)
{
    tr[t].l=l;
    tr[t].r=r;
    int ret=(r-l+1);
    tr[t].max=ret;
    tr[t].lmax=ret;
    tr[t].rmax=ret;
    tr[t].lazy=0;
    if(l==r)return(0);
    int mid=midt;
   maketree(ls,l,mid);
   maketree(rs,mid+1,r);
    return(0);
}

void pushdown(int t)
{
    if(tr[t].lazy==1)
    {
       tr[ls].lazy=1;
       tr[ls].rmax=tr[ls].r-tr[ls].l+1;
       tr[ls].lmax=tr[ls].rmax;
       tr[ls].max=tr[ls].rmax;
       tr[rs].lazy=1;
       tr[rs].rmax=tr[rs].r-tr[rs].l+1;
       tr[rs].lmax=tr[rs].rmax;
       tr[rs].max=tr[rs].rmax;

    }
    else
    {
       tr[ls].lazy=-1;
       tr[ls].rmax=0;
       tr[ls].lmax=0;
       tr[ls].max=0;

       tr[rs].lazy=-1;
       tr[rs].rmax=0;
       tr[rs].lmax=0;
       tr[rs].max=0;
    }
    tr[t].lazy=0;
}

void modify(int t,int l,int r,int tmp)
{
   if(l==tr[t].l&&r==tr[t].r)
    {
       tr[t].lazy=tmp;
       if(tmp==1)
       {
           intret=r-l+1;
          tr[t].max=ret;
          tr[t].lmax=ret;
          tr[t].rmax=ret;
       }
       else
       {
          tr[t].max=0;
          tr[t].lmax=0;
          tr[t].rmax=0;
       }
       return ;
    }

    if(tmp==tr[t].lazy)return ;

    if(tr[t].lazy)
    pushdown(t);

    int mid=midt;
   if(r<=mid)
   modify(ls,l,r,tmp);
    elseif(mid+1<=l)
   modify(rs,l,r,tmp);
    else
    {
       modify(ls,l,mid,tmp);
       modify(rs,mid+1,r,tmp);
    }

    intret=tr[ls].rmax+tr[rs].lmax;
   if(ret<tr[ls].max)
    ret=tr[ls].max;
   if(ret<tr[rs].max)
    ret=tr[rs].max;
    tr[t].max=ret;

   if(tr[rs].rmax==(tr[rs].r-tr[rs].l+1))
   tr[t].rmax=tr[rs].rmax+tr[ls].rmax;
    else
   tr[t].rmax=tr[rs].rmax;

   if(tr[ls].lmax==(tr[ls].r-tr[ls].l+1))
   tr[t].lmax=tr[ls].lmax+tr[rs].lmax;
    else
   tr[t].lmax=tr[ls].lmax;
}

int main()
{
    int n;
    int k;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
       maketree(1,1,n);
       int  tmp,l,r;
       for(int i=1;i<=k;i++)
       {
          scanf("%d",&tmp);
          if(tmp==3)
          printf("%d\n",tr[1].max);
           elseif(tmp==1)
           {
              scanf("%d%d",&l,&r);
              r=l+r-1;
              modify(1,l,r,-1);
           }
           else
           {
              scanf("%d%d",&l,&r);
              r=l+r-1;
              modify(1,l,r,1);
           }
       }
    }
    return 0;
}
原创粉丝点击