zoukankan      html  css  js  c++  java
  • HDU 1556 Color the ball 树状数组 题解

    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

    这是一条逆向向下更新才比較方便处理数据的题目。

    每一个根节点并不是记录和。而是记录改下标下面的节点更新了一次。

    所以更新的时候须要注意,小于区间的节点要-1操作。

    就这点技巧。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    int tree[100005];
    
    inline int lowbit(int x)
    {
    	return x & (-x);
    }
    
    void update(int x, int val, int len)
    {
    	while (x > 0)
    	{
    		tree[x] += val;
    		x -= lowbit(x);//最高点记录了一个区间内涂了多少次
    	}
    }
    
    int query(int x, int len)
    {
    	int ans = 0;
    	while (x <= len)
    	{
    		ans += tree[x];
    		x += lowbit(x);//全部根节点相加才等于答案
    	}
    	return ans;
    }
    
    int main()
    {
    	int n, a, b;
    	while (scanf("%d", &n) && n != 0)
    	{
    		fill(tree, tree+n+1, 0);
    		for(int i = 0; i < n; i++)  
    		{  
    			scanf("%d%d",&a,&b);  
    			update(b,1, n);  
    			update(a-1,-1, n);  
    
    		}  
    		for(int i=1;i<n;i++)  
    		{  
    			printf("%d ",query(i, n));  
    		}  
    		printf("%d
    ",query(n, n));  
    	}
    	return 0;
    }


    事实上也能够正向填表,和一般的查询和操作几乎相同,只是注意怎样更新节点。

    的确困难,非常考脑力的。要非常用力地想,呵呵。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int SIZE = 100005;
    int tree[SIZE];
    
    inline int lowbit(int x)
    {
    	return x & (-x);
    }
    
    void update(int x, int val, int len)
    {
    	while (x <= len)
    	{
    		tree[x] += val;
    		x += lowbit(x);
    	}
    }
    
    int query(int x)
    {
    	int ans = 0;
    	while (x > 0)
    	{
    		ans += tree[x];
    		x -= lowbit(x);
    	}
    	return ans;
    }
    
    int main()
    {
    	int n, a, b;
    	while (scanf("%d", &n) && n != 0)
    	{
    		fill(tree, tree+n+1, 0);
    		for(int i = 0; i < n; i++)  
    		{  
    			scanf("%d%d",&a,&b);  
    			update(a,1, n);  
    			update(b+1,-1, n);  
    
    		}  
    		for(int i=1;i<n;i++)  
    		{  
    			printf("%d ",query(i));  
    		}  
    		printf("%d
    ",query(n));  
    	}
    	return 0;
    }


    还有以下这位朋友的博客的直接使用数组解决这个问题,使得时间效率达到O(n)了,非常巧妙,高手!

    http://blog.csdn.net/u011560507/article/details/9673529


    仿他的写了个,呵呵。

    #include <algorithm>
    #include<cstdio>    
    using namespace  std; 
    const int SIZE = 100002; 
    int arr[SIZE];    
    int main()    
    {    
    	int N;    
    	while(scanf("%d",&N) && N)
    	{    
    		fill(arr, arr+N+1, 0);
    
    		for(int i = 1; i <= N; i++)
    		{    
    			int a, b;    
    			scanf("%d %d",&a, &b);    
    			arr[a]++;    
    			arr[b+1]--;    
    		}    
    		for(int i = 1; i < N; i++)
    		{    
    			arr[i] += arr[i-1];    
    			printf("%d ", arr[i]);    
    		}
    		printf("%d
    ", arr[N] + arr[N-1]);
    	}    
    	return 0;    
    } 



  • 相关阅读:
    PHP设置时区
    MySQL基本数据操作
    MySQL更改字段名
    MySQL修改数据表
    MySQL数据表的修改
    MySQL表级约束和列级约束
    MySQL外键约束的参照操作
    MySQL约束
    MySQL默认约束DEFAULT
    [Caffe]:关于*** Aborted at 1479432790 (unix time) try "date -d @1479432790" 错误的另一种原因
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/6733862.html
Copyright © 2011-2022 走看看