树状数组模板--Color the ball

倾然丶 夕夏残阳落幕 提交于 2020-02-10 22:39:48

Color the ball

 HDU - 1556 

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

1 3
2 1 1
3 2 2
4 3 3
5 3
6 1 1
7 1 2
8 1 3
9 0

Sample Output

1 1 1
3 2 1

思路不难,就是线段树||差分数组||普通树状数组||树状数组+差分的模板题

每次更新时区间各点+1,最后输出每个元素的值,总结来说就是区间更新+单点查询

 

TLE版本,单点修改,肯定超时,因为需要每次遍历左端点到右端点去更新,无法保持O(logn)的时间复杂度

普通正解:update数组表示从1到x每个数更新的次数,所以我们只需要update(L-1,-1)和update(R,1)表示[L,R]被更新的次数,相当于将[1,L-1]这个区间-1,再将[1,R]+1

差分+树状数组:在普通正解基础上,在每次修改区间时,利用差分数组的性质,只更新左端点L和R+1的位置

TLE:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<math.h>
 4 #include<stdlib.h>
 5 #include<cstring>
 6 #include<cstdio>
 7 #include<utility>
 8 #include<algorithm>
 9 #include<map>
10 #define lowbit(i) ((i)&(-i))
11 using namespace std;
12 typedef long long ll; 
13 inline int read(){
14     int X=0,w=0;char ch=0;
15     while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
16     while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
17     return w?-X:X;
18 }
19 /*------------------------------------------------------------------------*/
20 const int maxn=1e5+10; 
21 ll c[maxn];//树状数组
22 int n;
23 void update(int x,int v){
24     for(int i=x;i<=n;i+=lowbit(i)){
25         c[i]+=v;
26     }
27 } 
28 ll getsum(int x){//前x个整数之和
29     ll sum=0;
30     for(int i=x;i>0;i-=lowbit(i)){
31         sum+=c[i];
32     }
33     return sum;
34 }
35 ll query(int l,int r){
36     return getsum(r)-getsum(l-1);
37 }
38 int main( )
39 {    
40     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
41     //freopen("a.txt","r",stdin);
42     //freopen("a.txt","w",stdout);
43     
44     while(cin>>n){
45         if(n==0)break;
46         memset(c,0,sizeof(c));
47         
48         int l,r;
49         for(int i=1;i<=3;++i){
50             
51             cin>>l>>r;
52             for(int j=l;j<=r;++j){
53                 update(j,1);
54             }
55             
56         }
57         
58         for(int i=1;i<=n;++i){
59             cout<<query(i,i)<<" ";
60         }
61         cout<<endl;
62     }
63     return 0;
64 }
View Code

正解:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<math.h>
 4 #include<stdlib.h>
 5 #include<cstring>
 6 #include<cstdio>
 7 #include<utility>
 8 #include<algorithm>
 9 #include<map>
10 #define lowbit(i) ((i)&(-i))
11 using namespace std;
12 typedef long long ll; 
13 inline int read(){
14     int X=0,w=0;char ch=0;
15     while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
16     while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
17     return w?-X:X;
18 }
19 /*------------------------------------------------------------------------*/
20 const int maxn=1e5+10; 
21 ll c[maxn];//树状数组
22 int n;
23 void update(int x,int v){
24     for(int i=x;i>0;i-=lowbit(i)){
25         c[i]+=v;
26     }
27 } 
28 ll getsum(int x){//求第i个整数的值 
29     ll sum=0;
30     for(int i=x;i<=n;i+=lowbit(i)){
31         sum+=c[i];
32     }
33     return sum;
34 }
35 ll query(int l,int r){
36     return getsum(r)-getsum(l-1);
37 }
38 int main( )
39 {    
40     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
41     //freopen("a.txt","r",stdin);
42     //freopen("a.txt","w",stdout);
43     
44     while(cin>>n){
45         if(n==0)break;
46         memset(c,0,sizeof(c));
47         
48         int l,r;
49         for(int i=1;i<=n;++i){
50             
51             cin>>l>>r;
52             
53             update(r,1);
54             update(l-1,-1);
55             
56         }
57         
58         for(int i=1;i<n;++i){
59             cout<<getsum(i)<<" ";
60         }
61         cout<<getsum(n)<<endl;
62     }
63     return 0;
64 }
View Code

差分+树状数组

 1 #include<iostream>
 2 #include<cstring>
 3 #include<math.h>
 4 #include<stdlib.h>
 5 #include<cstring>
 6 #include<cstdio>
 7 #include<utility>
 8 #include<algorithm>
 9 #include<map>
10 #define lowbit(i) ((i)&(-i))
11 using namespace std;
12 typedef long long ll; 
13 inline int read(){
14     int X=0,w=0;char ch=0;
15     while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
16     while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
17     return w?-X:X;
18 }
19 /*------------------------------------------------------------------------*/
20 const int maxn=1e5+10; 
21 ll c[maxn];//树状数组
22 int n;
23 void update(int x,int v){
24     for(int i=x;i<=n;i+=lowbit(i)){
25         c[i]+=v;
26     }
27 } 
28 ll getsum(int x){
29     ll sum=0;
30     for(int i=x;i>0;i-=lowbit(i)){//前x个整数之和 
31         sum+=c[i];
32     }
33     return sum;
34 }
35 ll query(int l,int r){
36     return getsum(r)-getsum(l-1);
37 }
38 int main( )
39 {    
40     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
41     //freopen("a.txt","r",stdin);
42     //freopen("a.txt","w",stdout);
43     
44     while(cin>>n){
45         if(n==0)break;
46         memset(c,0,sizeof(c));
47         
48         int l,r;
49         for(int i=1;i<=n;++i){
50             
51             cin>>l>>r;
52             
53             //update(r,1);
54             //update(l-1,-1);
55             update(l,1);
56             update(r+1,-1);
57              
58         }
59         /*
60         差分数组的性质:差分数组的前x个数的和就是x的值 
61         */ 
62         for(int i=1;i<n;++i){
63             cout<<getsum(i)<<" ";
64         }
65         cout<<getsum(n)<<endl;
66     }
67     return 0;
68 }
View Code

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!