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