版权声明:原创博客 喜欢拿走 https://blog.csdn.net/qq_43004519/article/details/85159354
题目
个木桩排成一排,从左到右依次编号为 1,2,3…n1,2,3…n。每次给定 22 个整数 a,b(a≤b),蒜头君便骑上他的电动车从木桩 a 开始到木桩 b 依次给每个木桩涂一次颜色。但是 n 次以后 lele 已经忘记了第 i 个木桩已经涂过几次颜色了,你能帮他算出每个木桩被涂过几次颜色吗?
输入格式
第一行是一个整数 n(n≤100000)。
接下来的 n 行,每行包括两个整数 a, b (1≤a≤b≤n)。
输出格式
n 个整数,第 ii 个数代表第 i 个木桩总共被涂色的次数。
分析
以木桩建立树状数组,之前我们做的树状数组都是单点更新,并没有区间更新,那现在变换一下思路,以树状数组的前n项和再建立一个数组。
假设有8个木桩,输入2,6
change(a,1);
change(b+1,-1);
下标 1 2 3 4 5 6 7 8
树状数组c[8] 0 1 0 1 0 0 0 1
树状数组前n项和 sum[8] 0 1 1 1 1 1 0 0
注意观察sum数组的值,就可以明白树状数组的区间更新
AC
#include<iostream>/*树状数组的区间更新*/
using namespace std;
const int MAXN=1e5+1;
int tree[MAXN];
int n,a,b;
void change(int x,int v){
for(;x<=n;x+=x&(-x))
tree[x]+=v;
return;
}
int getsum(int x){
int re=0;
for(;x;x-=x&(-x))
re+=tree[x];
return re;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++){
cin>>a>>b;
change(a,1);//在getsum(i)构成的数组中就是从a开始都变为1
change(b+1,-1);//在getsum(i)构成的数组中就从b开始(因为b>a),因此从b开始都为0,而0到a也为0,只有a到b都是1,这就实现了区间更新
}
for(int i=1;i<=n;i++){
if(i==1)
cout<<getsum(i);
else
cout<<" "<<getsum(i);
}
return 0;//give me five
}