HDU1556 Color the ball 差分模板题

题意:给一段区间的部分染色,统计染色次数。
思路:差分。刚开始我也是感觉用线段树or树状数组做毕竟建树niubility而且lowbit也niubility。但是自从那天限时训练看到bin巨用差分,分分钟就敲出来了,就感觉真尼玛niubility。。。就看了看差分。
我现在所了解的差分就是可以处理区间某段同时加或减去一个数,然后进行查询的一些题目。这题太模板,代码在最后。不过想贴的是两种处理差分的办法:
1、复杂版

		int add=0;
		for(int i=1;i<=n;i++){
			add+=b[i];
			a[i]+=(a[i-1]+add);
		}
		for(int i=1;i<n;i++){
			printf("%d ",a[i]-a[i-1]);
		}printf("%d\n",a[n]-a[n-1]);

2、简单版

		for(int i=1;i<=n;i++){
			a[i]+=(a[i-1]+b[i]);
		}
		for(int i=1;i<n;i++){
			printf("%d ",a[i]);
		}printf("%d\n",a[n]);

两者我对比了一下,发现前者就是多了一个中间变量add,使得a[i]数组最后存的是前缀和,即第一个点到当前点所有染色次数,如果要求当前点的染色次数,那就需要用a[i]-a[i-1]来实现。
而后者就是直接存的当前点的染色次数,不需要再用前缀和来做差求得。
个人觉得两种都有利弊,对于单点查询显然后者好,但是对于区间查询来说,用前缀和作差求区间和显然要比遍历每个节点求和要好。
这就是主要的区别吧,下面上代码。

#include
#include
#include
#include
#include
#define ll long long
#define inf 0x3f3f3f3f
#define cl(a,b) memset(a,b,sizeof(a))
#define maxn 100005 
using namespace std;
int n;
int a[maxn],b[maxn];
void init(){
	for(int i=1;i<=n;i++){
		a[i]=b[i]=0;
	}
}
int main(){
	while(scanf("%d",&n)!=EOF){
		if(n==0) break;
		init();
		for(int i=1;i<=n;i++){
			int l,r;
			scanf("%d%d",&l,&r);
			b[l]++;
			b[r+1]--;
		}
		//————————————方法一 
		int add=0;
		for(int i=1;i<=n;i++){
			add+=b[i];
			a[i]+=(a[i-1]+add);
		}
		for(int i=1;i<n;i++){
			printf("%d ",a[i]-a[i-1]);
		}printf("%d\n",a[n]-a[n-1]);
		/*————————————方法二 
		for(int i=1;i<=n;i++){
			a[i]+=(a[i-1]+b[i]);
		}
		for(int i=1;i
	}
	return 0;
}

你可能感兴趣的:(差分,差分)