HDU 1556 Color the ball 线段树

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1556

参考实验室大佬链接:http://www.cnblogs.com/baocong/p/6698872.html

线段树区间更新模板题,还不是很熟练,晚上再写几道题。

个人理解:点更新容易理解,而区间更新主要特殊点在于为了减小更新时的时间复杂度,它引入了延迟标记-lazy,这个标记目的是标记这个节点,来表示此节点包含的区间(也就是儿子们)被更新过。

因此在进行更新以及查询操作的时候,需要先将当前节点的延迟标记(如果标记了的话)作用在它包含的区间也就是儿子们身上,也就是说将它的儿子更新。然后再继续对它的儿子们更新或者查询。

代码:

 1 #define maxn 300010
 2 struct node{
 3     int l, r, v;
 4     int lazy;
 5     node() {}
 6     node(int ll, int rr, int vv, int la): l(ll), r(rr), v(vv), lazy(la) {}
 7 };
 8 int n, a[maxn];
 9 node tree[maxn];
10 
11 int buildTree(int l, int r, int nodenum){
12     if(l == r){
13         tree[nodenum] = node(l, r, a[l], 0);
14         return a[l];
15     }
16     int mid = (l + r) >> 1;
17     buildTree(l, mid, nodenum << 1);
18     buildTree(mid + 1, r, nodenum << 1 | 1);
19     tree[nodenum] = node(l, r, 0, 0);
20     return 0;
21 }
22 void pushdown(int rt){
23     if(tree[rt].lazy){
24         tree[rt << 1].lazy += tree[rt].lazy;
25         tree[rt << 1 | 1].lazy += tree[rt].lazy;
26         tree[rt << 1].v += tree[rt].lazy;
27         tree[rt << 1 | 1].v += tree[rt].lazy;
28         tree[rt].lazy = 0;
29     }
30 }
31 
32 void update(int ql, int qr, int v, int l, int r, int nodenum){
33     if(l == ql && r == qr){
34         if(l == r) tree[nodenum].v += v;
35         else tree[nodenum].lazy += v;
36         return;
37     }
38     pushdown(nodenum);
39     int mid = (l + r) >> 1;
40     if(qr <= mid)
41         update(ql, qr, v, l, mid, nodenum << 1);
42     else if(ql <= mid){
43         update(ql, mid, v, l, mid, nodenum << 1);
44         update(mid + 1, qr, v, mid + 1, r, nodenum << 1 | 1);
45     }
46     else
47         update(ql, qr, v, mid + 1, r, nodenum << 1 | 1);
48 }
49 int query(int x, int l, int r, int nodenum){
50     if(l == r)
51         return tree[nodenum].v;
52     pushdown(nodenum);
53     int mid = (l + r) >> 1;
54     if(x > mid)
55         return query(x, mid + 1, r, nodenum << 1 | 1);
56     else
57         return query(x, l, mid, nodenum << 1); 
58 }
59 
60 
61 int main(){
62     while(scanf("%d", &n) && n){
63         memset(a, 0, sizeof(a));
64         buildTree(0, n - 1, 1);
65         for(int i = 0; i < n; i++){
66             int tma, tmb;
67             scanf("%d %d", &tma, &tmb);
68             tma--, tmb--;
69             update(tma, tmb, 1, 0, n - 1, 1);
70         }
71         for(int i = 0; i < n; i++){
72             if(i) 
73                 putchar(' ');
74             printf("%d", query(i, 0, n - 1, 1));
75         }
76         puts("");
77     }
78 }

题目:

Color the ball

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


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

 

posted @ 2017-06-05 15:06  EricJeffrey  阅读(187)  评论(0编辑  收藏  举报