Color the ball (线段树的区间更新问题)

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

题意:长度为n的区间,n次更新,每一次都将该区间的气球的颜色染一次色,问最终每一个气球染了几次色。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 const int MAXN=2e5+10;
  8 typedef long long ll;
  9 #define lson l,m,i<<1
 10 #define rson m+1,r,i<<1|1
 11 typedef struct Node
 12 {
 13     ll l,r;
 14     ll mid()
 15     {
 16         return (l+r)/2.0;
 17     }
 18     ll value;
 19 } Node;
 20 Node node[MAXN<<2];
 21 ll sum[MAXN<<2];
 22 ll add[MAXN<<2];
 23 void push_up(ll i)
 24 {
 25     sum[i]=sum[i<<1]+sum[i<<1|1];
 26 }
 27 void Build(ll l,ll r,ll i)
 28 {
 29     node[i].l=l;
 30     node[i].r=r;
 31     node[i].value=0;
 32     sum[i]=0;
 33     add[i]=0;
 34     if(l==r)
 35     {
 36         sum[i]=0;
 37         node[i].value=0;
 38         return ;
 39     }
 40     ll m=node[i].mid();
 41     Build(lson);
 42     Build(rson);
 43     push_up(i);
 44 }
 45 ll M;
 46 void Push_down(ll i,ll len)
 47 {
 48     if(add[i])
 49     {
 50         add[i<<1]+=add[i];
 51         add[i<<1|1]+=add[i];
 52         sum[i<<1]+=add[i]*(len-(len>>1));
 53         sum[i<<1|1]+=add[i]*(len>>1);
 54         add[i]=0;
 55     }
 56 }
 57 void query(ll l,ll r,ll i)
 58 {
 59     if(node[i].l==l&&node[i].r==r)
 60     {
 61         M+=sum[i];
 62         return;
 63     }
 64     ll m=node[i].mid();
 65     Push_down(i,node[i].r-node[i].l+1);
 66     if(r<=m)
 67         query(l,r,i<<1);
 68     else
 69     {
 70         if(l>m)
 71             query(l,r,i<<1|1);
 72         else
 73         {
 74             query(lson);
 75             query(rson);
 76         }
 77     }
 78 }
 79 void update(ll l,ll r,ll i,ll v)
 80 {
 81 
 82     if(node[i].r==r&&node[i].l==l)
 83     {
 84         add[i]+=v;
 85         sum[i]+=v*(r-l+1);
 86         return;
 87     }
 88     ll m=node[i].mid();
 89     Push_down(i,node[i].r-node[i].l+1);
 90     if(r<=m)
 91         update(l,r,i<<1,v);
 92     else
 93     {
 94         if(l>m)
 95             update(l,r,i<<1|1,v);
 96 
 97         else
 98         {
 99             update(l,m,i<<1,v);
100             update(m+1,r,i<<1|1,v);
101         }
102     }
103     push_up(i);
104 }
105 int main()
106 {
107     ll m,n,a,b,T,c;
108     ll flag=0;
109    while(scanf("%lld",&m)!=-1&&m)
110    {
111        ll k=m;
112        Build(1,m,1);
113        while(k--)
114        {
115            scanf("%lld%lld",&a,&b);
116            update(a,b,1,1);
117        }
118        for(ll i=1;i<=m;i++)
119        {
120            M=0;
121           query(i,i,1);
122           printf("%lld%c",M,i==m?'\n':' ');
123        }
124    }
125     return 0;
126 }
View Code

 

题解:线段树的区间更新问题,上篇博客每行代码有详细解释。

posted @ 2018-08-02 20:25  左手边五十米  阅读(182)  评论(0编辑  收藏  举报