zoukankan      html  css  js  c++  java
  • 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): 7941    Accepted Submission(s): 4070


    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
     


    Author
    8600
     


    Source
     


    Recommend
    LL   |   We have carefully selected several similar problems for you:  1542 1394 1255 2795 3397 
     
      线段树,区间更新,经典题
     
      题意:给你N个气球,不断刷新指定区间的颜色,刷新N次,最后输出每一个气球的刷新次数。
      思路
      很典型的区间更新的思想,那么很自然想到用线段树来做。线段树的每一个节点代表一个区间,并且有一个特定值来存储这个区间特定的信息,这里我们用这个特定值val记录该区间被刷新的次数。
      那么思路就有了,每一次刷新,用函数 Update(1,a,b),不断递归找到 [a,b] 区间,然后将该区间记录的值 val+1,表示该区间被刷新一次。注意必须找到区间,而且只刷新该区间的val值,如果遇到区间分开的情况,那么就分开来找。
      这样指定区间就存储了刷新的次数,我们最后要做的就是把每一条递归路径的刷新次数累加起来,最后到达的终点就是哪个气球的刷新次数。例如,有三个气球,第一个气球的刷新次数就是区间节点[1,3],[1,2]和[1,1]的val值相加。这个步骤可以在查询函数Query中做。
      代码
     1 #include <iostream>
     2 #include <stdio.h>
     3 using namespace std;
     4 #define MAXN 100010
     5 struct Node{
     6     int L,R;
     7     int val;    //被涂过的次数
     8 };
     9 Node a[MAXN*3+1];
    10 void Init(int d,int l,int r) //初始化线段树
    11 {
    12     if(l==r){   //递归出口
    13         a[d].L = l;
    14         a[d].R = r;
    15         a[d].val = 0;
    16         return ;
    17     }
    18 
    19     //初始化当前节点
    20     a[d].L = l;
    21     a[d].R = r;
    22     a[d].val = 0;
    23 
    24     //递归初始化孩子节点
    25     int mid = (l+r)/2;
    26     Init(d*2,l,mid);
    27     Init(d*2+1,mid+1,r);
    28 }
    29 void Update(int d,int l,int r)    //更新某一区间的值
    30 {
    31     if(a[d].L==l && a[d].R==r){  //递归出口。找到区间
    32         a[d].val++;
    33         return ;
    34     }
    35     if(a[d].L==a[d].R)  //递归出口。没有找到
    36         return ;
    37     //没找到
    38     int mid = (a[d].L+a[d].R)/2;
    39     if(mid>=r){  //去左孩子找
    40         Update(d*2,l,r);
    41     }
    42     else if(mid<l){ //去右孩子找
    43         Update(d*2+1,l,r);
    44     }
    45     else {  //中点在要查询区间的中间,两边都要找
    46         Update(d*2,l,mid);
    47         Update(d*2+1,mid+1,r);
    48     }
    49 }
    50 int Query(int d,int l,int r)    //查询
    51 {
    52     if(a[d].L==l && a[d].R==r)  //找到区间
    53         return a[d].val;
    54     if(a[d].L==a[d].R)
    55         return 0;
    56 
    57     int mid = (a[d].L+a[d].R)/2;
    58     if(mid>=r){  //去左孩子找
    59         return a[d].val + Query(d*2,l,r);
    60     }
    61     else if(mid<l){ //去右孩子找
    62         return a[d].val + Query(d*2+1,l,r);
    63     }
    64     else {  //中点在要查询区间的中间,两边都要找
    65         return a[d].val + Query(d*2,l,mid) + Query(d*2+1,mid+1,r);
    66     }
    67 }
    68 int main()
    69 {
    70     int N,A,B,i,sum;
    71     while(scanf("%d",&N)!=EOF && N){
    72         Init(1,1,N);
    73         for(i=1;i<=N;i++){  //输入并更新线段树
    74             scanf("%d%d",&A,&B);
    75             Update(1,A,B);
    76         }
    77         for(i=1;i<=N;i++){  //输出每一个气球被涂过的次数
    78             sum = Query(1,i,i);
    79             printf("%d",sum);
    80             if(i!=N) printf(" ");
    81         }
    82         printf("
    ");
    83     }
    84     return 0;
    85 }

    Freecode : www.cnblogs.com/yym2013

  • 相关阅读:
    自写 jQuery 大幅弹窗广告插件(不喜勿拍)
    反省:一个失败的产品
    javascript变量:全局?还是局部?这个得注意!
    前端工作常常会用到的一些经验技巧(三)
    Jquery伪选择器学习笔记
    前端工作常常会用到的一些经验技巧(二)
    (总结)工作中常用的js自定义函数——日期时间类
    js 数组引用 发现的问题
    一位资深程序员大牛给予Java初学者的学习路线建议(转)
    正则表达式
  • 原文地址:https://www.cnblogs.com/yym2013/p/3737247.html
Copyright © 2011-2022 走看看