线段树——简单篇

对节点进行操作

(1)hdu 1166 敌兵布阵
这是简单的练手题

View Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define size 50010

int sum[size<<2];

void PushUp(int rt)
{
    int ls,rs;
    ls=rt<<1;rs=rt<<1|1;
    sum[rt]=sum[ls]+sum[rs];
}

void build_tree(int l,int r,int rt)
{
    int m=(l+r)>>1;
    sum[rt]=0;
    if(l==r)
    {
        scanf("%d",&sum[rt]);
        return ;
    }
    build_tree(l,m,rt<<1);
    build_tree(m+1,r,rt<<1|1);
    PushUp(rt);
}

int query(int L,int R,int l,int r,int rt)
{
    int m=(l+r)>>1,res=0;
    if(L<=l&&r<=R)
        return sum[rt];
    if(L<=m)
        res+=query(L,R,l,m,rt<<1);
    if(R>m)
        res+=query(L,R,m+1,r,rt<<1|1);
    return res;
//    PushUp(rt);
}

void inpoint(int num,int goal,int l,int r,int rt)
{
    int m=(l+r)>>1;
    if(l==r)
    {
        sum[rt]+=num;
        return ;
    }
    if(goal<=m)
        inpoint(num,goal,l,m,rt<<1);
    if(goal>m)
        inpoint(num,goal,m+1,r,rt<<1|1);
    PushUp(rt);
}

int main()
{
    int i,t,n,a,b;
    char str[10];
    //freopen("test","r",stdin);
    scanf("%d",&t);
    for(i=1;i<=t;i++)
    {
        printf("Case %d:\n",i);
        scanf("%d",&n);
        build_tree(1,n,1);
        while(scanf("%s",str))
        {
            if(strcmp(str,"End")==0)
                break;
            scanf("%d %d",&a,&b);
            if(strcmp(str,"Query")==0)
            {
                printf("%d\n",query(a,b,1,n,1));
            }
            else if(strcmp(str,"Add")==0)
                inpoint(b,a,1,n,1);
            else if(strcmp(str,"Sub")==0)
                inpoint(-b,a,1,n,1);
        }
    }
    return 0;
}

( 2 ) hdu 1754 I Hate It

  也是一道水题,维护的最大值

View Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define size 200010
#define INF 1000000
#define max(a,b) (a)>(b)?(a):(b)

int sum[size<<2];

void Pushup(int rt)
{
    sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
}
void build (int l,int r,int rt)
{
    if(l==r)
    {
        scanf("%d",&sum[rt]);
        return;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    Pushup(rt);
}

int query(int li,int ri,int l,int r,int rt)
{
    int m=(l+r)>>1;
    int res1=-INF,res2=-INF;
    if(l>=li && r<=ri)
        return sum[rt];
    if(li<=m)
        res1=query(li,ri,l,m,rt<<1);
    if(ri>m)
        res2=query(li,ri,m+1,r,rt<<1|1);
    return max(res1,res2);
}

void change(int goal,int num,int l,int r,int rt)
{
    int m=(l+r)>>1;
    if(l==r)
    {
        sum[rt]=num;
        return ;
    }
    if(goal<=m)
        change(goal,num,l,m,rt<<1);
    else
        change(goal,num,m+1,r,rt<<1|1);
    Pushup(rt);
}

int main()
{
    int n,m,i,a,b;
    char s[3];
 //   freopen("test","r",stdin);
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        build(1,n,1);
        for(i=0;i<m;i++)
        {
            scanf("%s%d%d",s,&a,&b);
            if(s[0]=='Q')
                printf("%d\n",query(a,b,1,n,1));
            else
                change(a,b,1,n,1);
        }
    }
    return 0;
}

(3)hdu 2795 Billboard 

线段树最低层的节点一共有h个,每个大小是w,当贴上海报,减去海报的长,维护最大的点就OK了

View Code
#include<stdio.h>
#include<string.h>
#define size 200005

struct node
{
    int l,r,m;
};
node tree[size<<2];
int a;
int h,w,n;

void pushup(int rt)
{
    if( tree[rt<<1].m>=tree[rt<<1|1].m)
        tree[rt].m=tree[rt<<1].m;
    else
        tree[rt].m=tree[rt<<1|1].m;
}

void build(int l,int r,int rt)
{
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].m=w;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
}

void query(int num,int rt)
{
    if(tree[rt].l==tree[rt].r)
    {
        tree[rt].m-=num;
        printf("%d\n",tree[rt].l);
        return ;
    }
    if(tree[rt<<1].m>=num)
        query(num,rt<<1);
    else
        query(num,rt<<1|1);
    pushup(rt);
}

int main()
{
    while(scanf("%d%d%d",&h,&w,&n)!=EOF)
    {
        if(h>n)
            h=n;
        build(1,h,1);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a);
            if(tree[1].m<a)
                printf("-1\n");
            else
                query(a,1);
        }
    }
    return 0;
}

(4)poj 2828 Buy Tickets 

注意:倒叙,插入的位子是空格数,维护的是空格数的个数。

View Code
#include<cstdio>
#include<string>
#define size 200005

struct node
{
    int l,r;
    int blank;
};
node tree[size<<2];
struct point{
    int po,va;
};
point num[size];
int ans[size];

void pushup(int rt)
{
    tree[rt].blank=tree[rt<<1].blank+tree[rt<<1|1].blank;
}
void build(int l,int r,int rt)
{
    tree[rt].l=l;
    tree[rt].r=r;
    if(l==r)
    {
        tree[rt].blank=1;
        return ;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}
void insert(int b,int va,int rt)
{
    if(tree[rt].l==tree[rt].r)
    {
        tree[rt].blank--;
        ans[tree[rt].l]=va;
        return ;
    }
    if(tree[rt<<1].blank>=b)
        insert(b,va,rt<<1);
    else
        insert(b-tree[rt<<1].blank,va,rt<<1|1);
    pushup(rt);
}
int main()
{
    int n,i;
 //   freopen("test","r",stdin);
    while(scanf("%d",&n)!=EOF)
    {
        build(1,n,1);
        for(i=1;i<=n;i++)
            scanf("%d%d",&num[i].po,&num[i].va);
        for(i=n;i>0;i--)
            insert(num[i].po+1,num[i].va,1);
        for(i=1;i<=n;i++)
        {
            if(i!=1)
                printf(" ");
            printf("%d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}

 

对段进行更新

 (1)hdu1698 Just a Hook

注意lazy数组的使用;

View Code
#include<cstdio>
#include<string>
#define size 100005

struct node
{
    int l,r;
    int sum;
    int lazy;
};
node tree[size<<2];
int ans[size];

void pushup(int rt)
{
    tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
}
void pushdown(int rt)
{
    tree[rt<<1].lazy=tree[rt].lazy;
    tree[rt<<1|1].lazy=tree[rt].lazy;
    tree[rt<<1].sum=(tree[rt<<1].r-tree[rt<<1].l+1)*tree[rt].lazy;
    tree[rt<<1|1].sum=(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*tree[rt].lazy;
    tree[rt].lazy=0;
}
void build(int l,int r,int rt)
{
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].sum=1;
    tree[rt].lazy=0;
    if(l==r)
        return ;
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}

void change(int l,int r,int z,int rt)
{
    if(tree[rt].l==l && tree[rt].r==r)
    {
        tree[rt].lazy=z;
        tree[rt].sum=(r-l+1)*z;
        return ;
    }
    if(tree[rt].lazy!=0)
        pushdown(rt);
    int m=(tree[rt].l+tree[rt].r)>>1;
    if(m>=r)
        change(l,r,z,rt<<1);
    else if(m<l)
        change(l,r,z,rt<<1|1);
    else
    {
        change(l,m,z,rt<<1);
        change(m+1,r,z,rt<<1|1);
    }
    pushup(rt);
}
int main()
{
    int n,i,t,q;
    int l,r,z;
    freopen("test","r",stdin);
    scanf("%d",&t);
    for(int as=1;as<=t;as++)
    {
        scanf("%d%d",&n,&q);
        build(1,n,1);

        for(i=0;i<q;i++)
        {
            scanf("%d%d%d",&l,&r,&z);
            change(l,r,z,1);
        }
        printf("Case %d: The total value of the hook is %d.\n",as,tree[1].sum);
    }
    return 0;
}

(2)poj3468 A Simple Problem with Integers

题很简单,但是要注意:输入输出,会发生溢出

View Code
#include<cstdio>
#include<string>
#define size 100005

struct node
{
    int l,r;
    __int64 sum;
    __int64 lazy;
};
node tree[size<<2];;

void pushup(int rt)
{
    tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
}
void pushdown(int rt)
{
    tree[rt<<1].lazy+=tree[rt].lazy;
    tree[rt<<1|1].lazy+=tree[rt].lazy;
    tree[rt<<1].sum+=(tree[rt<<1].r-tree[rt<<1].l+1)*tree[rt].lazy;
    tree[rt<<1|1].sum+=(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*tree[rt].lazy;
    tree[rt].lazy=0;
}
void build(int l,int r,int rt)
{
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].sum=0;
    tree[rt].lazy=0;
    if(l==r)
    {
        scanf("%I64d",&tree[rt].sum);
        return ;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}

void change(int l,int r,int z,int rt)
{
    if(tree[rt].l==l && tree[rt].r==r)
    {
        tree[rt].lazy+=z;
        tree[rt].sum+=(r-l+1)*z;
        return ;
    }
    if(tree[rt].lazy!=0)
        pushdown(rt);
    int m=(tree[rt].l+tree[rt].r)>>1;
    if(m>=r)
        change(l,r,z,rt<<1);
    else if(m<l)
        change(l,r,z,rt<<1|1);
    else
    {
        change(l,m,z,rt<<1);
        change(m+1,r,z,rt<<1|1);
    }
    pushup(rt);
}

__int64 query(int l,int r,int rt)
{
    if(tree[rt].l==l && tree[rt].r==r)
    {
        return tree[rt].sum;
    }
    if(tree[rt].lazy!=0)
        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 query(l,m,rt<<1)+query(m+1,r,rt<<1|1);
}

int main()
{
    int i,n,q;
    int l,r,z;
    char s[3];
  //  freopen("test","r",stdin);
    scanf("%d%d",&n,&q);
    build(1,n,1);
    for(i=0;i<q;i++)
    {
        scanf("%s",&s);
        if(s[0]=='Q')
        {
            scanf("%d%d",&l,&r);
            printf("%I64d\n",query(l,r,1));
        }
        else
        {
            scanf("%d%d%d",&l,&r,&z);
            change(l,r,z,1);
        }
    }
    return 0;
}

(3)poj2528 Mayor’s posters

主要是离散化,这是一个重点,为自己确定一个模板,以后可以接着用。

还有 在最大的范围要注意。

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define size 40005
using namespace std;
struct node
{
    int l,r;
    int sum;
    int lazy;
};
node tree[size<<2];;
int point[size];
int vis[size],ans;

void pushup(int rt)
{
    if(tree[rt<<1].sum==tree[rt<<1|1].sum)
        tree[rt].sum=tree[rt<<1].sum;
    else
        tree[rt].sum=-1;
}
void pushdown(int rt)
{
    tree[rt<<1].lazy=tree[rt].lazy;
    tree[rt<<1|1].lazy=tree[rt].lazy;
    tree[rt<<1].sum=tree[rt].sum;
    tree[rt<<1|1].sum=tree[rt].sum;
    tree[rt].lazy=0;
}

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

void change(int l,int r,int rt,int i)
{
    if(tree[rt].l==l && tree[rt].r==r)
    {
        tree[rt].lazy=1;
        tree[rt].sum=i;
        return ;
    }
    if(tree[rt].lazy!=0)
        pushdown(rt);
    int m=(tree[rt].l+tree[rt].r)>>1;
    if(m>=r)
        change(l,r,rt<<1,i);
    else if(m<l)
        change(l,r,rt<<1|1,i);
    else
    {
        change(l,m,rt<<1,i);
        change(m+1,r,rt<<1|1,i);
    }
    pushup(rt);
}

void query(int rt)
{
    if(tree[rt].sum==0)
        return;
    if(tree[rt].sum!=-1)
    {
        if(vis[tree[rt].sum]==0)
        {
            vis[tree[rt].sum]=1;
            ans++;
            return;
        }
        return;
    }
    if(tree[rt].lazy!=0)
        pushdown(rt);
    query(rt<<1);
    query(rt<<1|1);
}

int find(int key,int n)
{
    int l = 0 , r = n - 1;
    while (l <= r) {
        int m = (l + r) >> 1;
        if (point[m] == key) return m;
        if (point[m] < key) l = m + 1;
        else r = m - 1;
    }
    return -1;
}

int main()
{
    int i,n,t,li,ri;
    int l[size],r[size];
 //   freopen("test","r",stdin);
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int nn=0;
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&l[i],&r[i]);
            point[nn++]=l[i];
            point[nn++]=r[i];
        }
        sort(point , point + nn);
        int m = 1;
        for (i = 1 ; i < nn; i ++) {
            if (point[i] != point[i-1]) point[m ++] = point[i];
        }
        for (i = m - 1 ; i > 0 ; i --) {
            if (point[i] != point[i-1] + 1) point[m ++] = point[i-1] + 1;
        }
        sort(point , point + m);
        build(0,m-1,1);
        memset(vis,0,sizeof(vis));
        ans=0;
        for(i=0;i<n;i++)
        {
            li=find(l[i],m);
            ri=find(r[i],m);
    //        printf("%d %d\n",li,ri);
            change(li,ri,1,i+1);
        }
        query(1);
        printf("%d\n",ans);
    }
    return 0;
}

 

 

 

posted @ 2012-09-19 20:45  feng_linxu  Views(127)  Comments(0)    收藏  举报