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
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 }
正解:

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 }
差分+树状数组

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 }
来源:https://www.cnblogs.com/simaomao/p/12293006.html
