用差分数组和树状数组思路是一样的,都是运用到差分的原理,d[i] = a[i] - a[i-1],当我们在区间 [l,r] 涂气球时,只需要在d[l] -= 1,d[r+1] += 1,然后还需用到前缀和(sum[i] = a[1]+a[2]+…+a[i]),最后求i点的涂色次数:sum[i] = sum[i-1] + d[i]。
差分数组
//#include <bits/stdc++.h>
#include <cstdio>
#include <queue>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#define ll long long
#define maxn 1009000
using namespace std;
const long long N = 1000000;
const int inf = 0x3f3f3f3f;
int n,d[N],sum[N];
int main() {
while(scanf("%d",&n) && n) {
memset(d, 0, sizeof d);
memset(sum, 0,sizeof sum);
for (int i = 1; i <= n; i++) {
int x,y;
scanf("%d%d",&x,&y);
d[x] += 1;
d[y+1] -= 1;
}
//因为所有气球都没有被染过色,所以sum的初始化直接为0
for(int i=1; i<=n; i++){
sum[i] = sum[i-1] + d[i];
}
for(int i=1; i<n; i++)
printf("%d ",sum[i]);
printf("%d\n",sum[n]);
}
return 0;
}
树状数组:
树状数组存储很特殊:(c为树状数组的存储)
c[1] = a[1];
c[2] = a[1] + a[2];
c[3] = a[3];
c[4] = a[1] + a[2] + a[3] + a[4];
c[5] = a[5];
c[6] = a[5] + a[6];
c[7] = a[7];
c[8] = a[8] + a[7] + a[6] + a[5] + a[4] + a[3] + a[2] + a[1];
规律是啥呢?(想出这个的人真的很厉害。。)
举个栗子 c[4],4的二进制是100,最后有两个0,所以他可以存储2的2次方个数,也就是4个数。
再举个栗子 c[5], 5的二进制是101,最后没有0,所以他可以存储2的0次方个数,也就是1个数。
所以综上所述:
c[i]=a[i - (2^k) + 1] + a[i - (2^k) + 2] + a[i - (2^k) + 3] + … + a[i] ;
那么 2^k 怎么来呢?
又有前人帮我们铺好了路:
举个栗子 6的二进制:110, -6的二进制:001 + 1 = 010,那么 6&(-6) = 2。
2就是我们要求的2^k。
代码就是:
int lowbit(int x){
return x & (-x);
}
那么按照结论:c[i]=a[i - (2^k) + 1] + a[i - (2^k) + 2] + a[i - (2^k) + 3] + … + a[i] ;
我们可以得到代码:
int getsum(int x){ //求sum[x]
int ans = 0;
for(int i = x; i>0; i -= lowbit(i)){
ans += c[i];
}
return ans;
}
然后就是树状数组的修改了
代码:
void update(int x, int y){ //给处于x位置上的点加y。
for(int i=x; i<=n; i += lowbit(i)){
c[i] += y;
}
}
最后就是本题的代码:
#include <cstdio>
#include <queue>
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#define ll long long
#define maxn 1009000
using namespace std;
const long long N = 1000000;
const int inf = 0x3f3f3f3f;
int n,c[N],vis[N],sum[N];
int lowbit(int x){
return x & (-x);
}
void update(int x, int y){
for(int i=x; i<=n; i += lowbit(i)){
c[i] += y;
}
}
int getsum(int x){
int ans = 0;
for(int i = x; i>0; i -= lowbit(i)){
ans += c[i];
}
return ans;
}
int main() {
while(scanf("%d",&n) && n) {
memset(c, 0, sizeof c);
for (int i = 1; i <= n; i++) {
int x,y;
scanf("%d%d", &x,&y);
update(x, 1);
update(y+1, -1);
}
for(int i=1; i<n; i++){
printf("%d ",getsum(i));
}
printf("%d\n",getsum(n));
}
return 0;
}