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;    
    } 



  • 相关阅读:
    java反射注解妙用-获取所有接口说明
    npm设置和查看仓库源
    正则表达式-linux路径匹配
    在vue中使用echarts图表
    设计模式-简单工厂模式
    设计模式
    Redis实现世界杯排行榜功能(实战)
    开发十五、k3cloud单据的附件自动上传到钉钉的审批单中
    微盟与金蝶k3cloud、erp库存对接
    开发一、k3cloud内服务工单过滤在库批号
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/6733862.html
Copyright © 2011-2022 走看看