HDU 1556 Color the ball(线段树的区间更新【注释】)

Color the ball

Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 15092 Accepted Submission(s): 7514

Problem Description
N个气球排成一排,从左到右依次编号为1,2,3….N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽”牌电动车从气球a开始到气球b依次给每个气球涂一次颜色。但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗?

Input
每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <= N)。
当N = 0,输入结束。

Output
每个测试实例输出一行,包括N个整数,第I个数代表第I个气球总共被涂色的次数。

Sample Input
3
1 1
2 2
3 3
3
1 1
1 2
1 3
0

Sample Output
1 1 1
3 2 1

题意在这里就不多做介绍了,这个题就是典型的线段树的区间更新题目。

区间更新:就是把要更新的区间要增加的值直接加在这个区间上就可以了,并不需要去加到每一个点上,加在区间上,最后再统一的求和,节省了大量的时间,提高了时间效率。其他的东西都在代码中。

下面是AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct node
{
    int right,left,val;
} c[300005];

int sum[100005];
void build_tree(int root,int l,int r)//建树
{
    c[root].left=l;
    c[root].right=r;
    c[root].val=0;//表示这个节点有多少个数
    if(c[root].left==c[root].right)
    {
        return ;
    }
    int mid=(l+r)/2;
    build_tree(root*2,l,mid);
    build_tree(root*2+1,mid+1,r);
}

void update_tree(int root,int l,int r)//区间更新
{
    if(c[root].left==l&&c[root].right==r)//如果找到了要更新的区间,那么直接改变这个区间的值,而不用去改变每个点的值
    {
        c[root].val++;
        return ;
    }
    int mid=(c[root].right+c[root].left)/2;
    if(mid<l)
    {
        update_tree(root*2+1,l,r);
    }
    else if(mid>=r)
    {
        update_tree(root*2,l,r);
    }
    else
    {
        update_tree(root*2,l,mid);
        update_tree(root*2+1,mid+1,r);
    }
}

void sum_tree(int root)//区间求和
{
    for(int i=c[root].left; i<=c[root].right; i++)//只要某个点在这个区间内。这个点的值就加上这个区间的价值
    {
        sum[i]+=c[root].val;
    }
    if(c[root].left==c[root].right)//加到最后的单点区间就结束
        return ;
    sum_tree(root*2);
    sum_tree(root*2+1);
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        if(n==0)
            break;
        memset(sum,0,sizeof(sum));
        build_tree(1,1,n);
        for(int i=0; i<n; i++)
        {
            int a,b;
            scanf("%d %d",&a,&b);
            update_tree(1,a,b);
        }
        sum_tree(1);//求和函数
        for(int i=1; i<n; i++)
        {
            printf("%d ",sum[i]);
        }
        printf("%d\n",sum[n]);
    }
    return 0;
}

你可能感兴趣的:(HDU)