线段树——提高篇

虽然线段树我没有学多久,但是我的格式被好几个人鄙弃,从今天开始,我要更改线段树的格式。

  pushup( rt  )  向下更新lazy 等节点信息。

  pushdown( rt )  向上更新

 

(1) hdu 3954 Level up

    活用 lazy 标志,

 新的格式:

View Code
#include<stdio.h>
#include<string.h>
#include<math.h>

int max(int a,int b)
{
    return a>b?a:b;
}
int min(int a,int b)
{
    return a<b?a:b;
}
const int size=10005;

typedef struct node
{
    int l,r;
    int exp,lev;
    int lazy;
    int mis_dis;
}node;
node tree[size*5];
int a[15],k;

void pushdown(int rt)
{
    int nl=rt<<1,nr=rt<<1|1;
    tree[nl].exp+=tree[rt].lazy*tree[nl].lev;
    tree[nl].lazy+=tree[rt].lazy;
    tree[nl].mis_dis-=tree[rt].lazy;

    tree[nr].exp+=tree[rt].lazy*tree[nr].lev;
    tree[nr].lazy+=tree[rt].lazy;
    tree[nr].mis_dis-=tree[rt].lazy;
    tree[rt].lazy=0;
}

void pushup(int rt)
{
    tree[rt].exp=max(tree[rt<<1].exp,tree[rt<<1|1].exp);
    tree[rt].lev=max(tree[rt<<1].lev,tree[rt<<1|1].lev);
    tree[rt].mis_dis=min(tree[rt<<1].mis_dis,tree[rt<<1|1].mis_dis);
}

void build(int l,int r,int rt)
{
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].exp=0;
    tree[rt].lazy=0;
    tree[rt].lev=1;
    tree[rt].mis_dis=a[1];
    if(l==r)
        return ;
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
}

void add(int l,int r,int e,int rt)
{
    if(tree[rt].l==tree[rt].r)         //更新叶子
    {
        tree[rt].exp+=tree[rt].lev*e;
        while(tree[rt].exp>=a[tree[rt].lev])
            tree[rt].lev++;
        tree[rt].mis_dis=(a[tree[rt].lev]-tree[rt].exp)/tree[rt].lev;
        if((a[tree[rt].lev]-tree[rt].exp)%tree[rt].lev)
            tree[rt].mis_dis++;
        return;
    }
    if(tree[rt].l==l && tree[rt].r==r)
    {
        if(e>=tree[rt].mis_dis)
        {
            if(tree[rt].lazy)
                pushdown(rt);
            add(tree[rt<<1].l,tree[rt<<1].r,e,rt<<1);
            add(tree[rt<<1|1].l,tree[rt<<1|1].r,e,rt<<1|1);
            pushup(rt);
        }
        else
        {
            tree[rt].exp+=tree[rt].lev*e;
            tree[rt].lazy+=e;
            tree[rt].mis_dis-=e;
        }
        return ;
    }
    if(tree[rt].lazy)
        pushdown(rt);
    int m=(tree[rt].l+tree[rt].r)>>1;
    if(m>=r)
        add(l,r,e,rt<<1);
    else if(m<l)
        add(l,r,e,rt<<1|1);
    else
    {
        add(l,m,e,rt<<1);
        add(m+1,r,e,rt<<1|1);
    }
    pushup(rt);
}

int query(int l,int r,int rt)
{
    if(tree[rt].l==l && tree[rt].r==r)
        return tree[rt].exp;
    if(tree[rt].lazy)
        pushdown(rt);
    int m=(tree[rt].l+tree[rt].r)>>1;
    if(m>=r)
        return query(l,r,rt<<1);
    else if(m<l)
        return query(l,r,rt<<1|1);
    else
        return max(query(l,m,rt<<1),query(m+1,r,rt<<1|1));
}

int main()
{
    int t,i;
    int n,qw,li,ri,ei;
    char str[5];
    scanf("%d",&t);
    for(int as=1;as<=t;as++)
    {
        printf("Case %d:\n",as);
        scanf("%d%d%d",&n,&k,&qw);
        for( i=1;i<k;i++)
            scanf("%d",&a[i]);
        a[k]=1<<30;
        build(1,n,1);
        for(i=0;i<qw;i++)
        {
            scanf("%s%d%d",str,&li,&ri);
            if(str[0]=='W')
            {
                scanf("%d",&ei);
                add(li,ri,ei,1);
            }
            else
            {
                printf("%d\n",query(li,ri,1));
            }

        }
        printf("\n");
    }
    return 0;
}

 

区间合并

()poj 3667 Hotel

基本的区间合并,主要是写时要细心就好。

View Code
  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<algorithm>
  4 #define size 50005
  5 using namespace std;
  6 
  7 struct node
  8 {
  9     int l,r;
 10     int ls,rs,m;
 11     int lazy;
 12 }tree[size<<2];
 13 
 14 void build(int l,int r,int rt)
 15 {
 16     tree[rt].l=l;
 17     tree[rt].r=r;
 18     tree[rt].ls=tree[rt].rs=tree[rt].m=r-l+1;
 19     tree[rt].lazy=-1;
 20     if(l==r)
 21         return ;
 22     int mid=(l+r)>>1;
 23     build(l,mid,rt<<1);
 24     build(mid+1,r,rt<<1|1);
 25 }
 26 void pushdown(int rt)
 27 {
 28     tree[rt<<1].lazy=tree[rt<<1|1].lazy=tree[rt].lazy;
 29     tree[rt<<1].ls=tree[rt<<1].rs=tree[rt<<1].m=tree[rt].lazy?0:tree[rt<<1].r-tree[rt<<1].l+1;
 30     tree[rt<<1|1].ls=tree[rt<<1|1].rs=tree[rt<<1|1].m=tree[rt].lazy?0:tree[rt<<1|1].r-tree[rt<<1|1].l+1;
 31     tree[rt].lazy=-1;
 32 }
 33 void pushup(int rt)
 34 {
 35     tree[rt].ls=tree[rt<<1].ls;
 36     tree[rt].rs=tree[rt<<1|1].rs;
 37     if(tree[rt].ls==tree[rt<<1].r-tree[rt<<1].l+1)
 38         tree[rt].ls+=tree[rt<<1|1].ls;
 39     if(tree[rt].rs==tree[rt<<1|1].r-tree[rt<<1|1].l+1)
 40         tree[rt].rs+=tree[rt<<1].rs;
 41     tree[rt].m=max(max(tree[rt<<1].m,tree[rt<<1|1].m),tree[rt<<1].rs+tree[rt<<1|1].ls);
 42 }
 43 
 44 int query(int a,int rt)
 45 {
 46     if(tree[rt].l==tree[rt].r)
 47         return tree[rt].l;
 48     if(tree[rt].lazy!=-1)
 49         pushdown(rt);
 50     if(tree[rt<<1].m>=a)
 51         return query(a,rt<<1);
 52     else if(tree[rt<<1].rs+tree[rt<<1|1].ls>=a)
 53         return tree[rt<<1].r-tree[rt<<1].rs+1;
 54     else
 55         return query(a,rt<<1|1);
 56 }
 57 
 58 void update(int li,int ri,int t,int rt)
 59 {
 60     if(tree[rt].l==li && tree[rt].r==ri)
 61     {
 62         tree[rt].lazy=t;
 63         tree[rt].ls=tree[rt].rs=tree[rt].m=t?0:ri-li+1;
 64         return ;
 65     }
 66     if(tree[rt].lazy!=-1)
 67         pushdown(rt);
 68     int mid=(tree[rt].l+tree[rt].r)>>1;
 69     if(ri<=mid)
 70         update(li,ri,t,rt<<1);
 71     else if(li>mid)
 72         update(li,ri,t,rt<<1|1);
 73     else
 74     {
 75         update(li,mid,t,rt<<1);
 76         update(mid+1,ri,t,rt<<1|1);
 77     }
 78     pushup(rt);
 79 }
 80 
 81 int main()
 82 {
 83     int n,m,i;
 84     int flag,a,x;
 85     scanf("%d%d",&n,&m);
 86     build(1,n,1);
 87     for(i=0;i<m;i++)
 88     {
 89         scanf("%d",&flag);
 90         if(flag==1)
 91         {
 92             scanf("%d",&a);
 93             if(tree[1].m<a)
 94                 printf("0\n");
 95             else
 96             {
 97                 int ans=query(a,1);
 98                 printf("%d\n",ans);
 99                 update(ans,ans+a-1,1,1);
100             }
101         }
102         else
103         {
104             scanf("%d%d",&x,&a);
105             update(x,x+a-1,0,1);
106         }
107     }
108     return 0;
109 }

 还有 :hdu 3308 LCIS    (求区间内最长连续递增的个数 )(又增加乐两个变量,还有,注意query的操作)

 

 

 

 

 

 

posted @ 2012-09-20 15:02  feng_linxu  Views(150)  Comments(0)    收藏  举报