题目链接: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,输入结束。
当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