题意:http://acm.hdu.edu.cn/showproblem.php?pid=1556
N个气球排成一排,从左到右依次编号为1,2,3…N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色。但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗?
N <= 100000,1 <= a <= b <= N
差分数组简介:
即维护一个数组d[] ,里面记录原数组每一项与前一项的差值,那么原数组中的每一个数都可以用d数组中对应的前缀和表示。再说题目中区间修改的问题:因为每一次操作使区间[a,b]的数增加1,区间段中每个数增加了相同的数,那么d[]数组的维护我们可以通过对d[a],d[b+1]的操作实现,即d[a]+=1,d[b+1]-=1(加上/减去改变量)
(支持“先进性区间修改,最后再统一查询”的题目,但边修改边查询的题目只能用其他数据结构)
借助差分数组就将原题的区间修改转化成了单点的修改,最后求每项前缀和的问题,后面的问题就可以用树状数组解决
代码:
#include <iostream>
#include <string.h>
#include<stdio.h>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
typedef long long LL;
using namespace std;
#define chl (root<<1)
#define chr ((root<<1)|1)
#define mid ((l+r)>>1)
const LL INF=2e9;
const int manx=1e5+10;
int n,a,b,c[manx];
void add(int x,int val)
{
if(!x)return;
while(x<=n)
{
c[x]+=val;
x+=x&(-x);
}
}
int query(int x)
{
int ans=0;
while(x)
{
ans+=c[x];
x-=x&(-x);
}
return ans;
}
int main()
{
while(scanf("%d",&n),n)
{
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
add(a,1);
add(b+1,-1);
}
for(int i=1;i<=n;i++)
printf("%d%c",query(i),i==n?'\n':' ');
}
}