这题可以说是树状数组区间更新,单点查询的模板题。
对于树状数组的区间更新,单点查询,其实就是维护一个差分数组。以该题为例:
定义两个数组a[],b[]。a[]数组表示气球涂色次数,初始均为0。设b[n] = a[n] - a[n-1](即b[]数组是a[]数组的一个差分数组),因为a[]数组初始均为0,所以b[]数组初始也为0,且b[1]+b[2]+…+b[n] = a[n] - a[0] = a[n]。
假设这里我们要对区间为[l,r]的气球图n次色,也就是对a[]数组的[l,r]区间都加n。即:a[1]′=a[1],…,a[l−1]′=a[l−1],a[l]′=a[l]+n,…,a[r]′=a[r]+n,a[r+1]′=a[r+1],…那么对于b[1],…,b[l−1],b[l+1],…,b[r],b[r+2],…不会变(区间外部不变导致b[1−l]和b[r+2−n]不变,区间内部增量相同导致b[l+1−r]不变),但是b[l]会+n,b[r+1]会−n。
这就转变成了对b[]数组的单点更新、区间查询。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int sz[maxn],n;
int lowbit(int x)
{
return x&(-x);
}
int update(int x,int num)
{
while(x<=n)
{
sz[x] += num;
x += lowbit(x);
}
}
int query(int x)
{
int ans = 0;
while(x>0)
{
ans += sz[x];
x -= lowbit(x);
}
return ans;
}
int main()
{
int a,b;
while(~scanf("%d",&n)&&n!=0)
{
memset(sz,0,sizeof(sz));
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
update(a,1);
update(b+1,-1);
}
for(int i=1;i<=n;i++) printf("%d%c",query(i),(i==n ? '\n' : ' '));
}
return 0;
}