[SDOI2009]HH的项链 解题报告

一、这道题。。据说有大神考场上的时候搞了一坨线段树实现了在线。。

二、离线是早就想到了,但是一开始我是按左端点扫的。。导致。。相当麻烦,还做了个前缀和什么的。

三、其实如果按右端点扫,就很简单了!

对于许多相同的数,我们完全可以只保存当前它们最右边那个,然后被保存的数被置1,没保存的置0,于是就成了简单的区间求和了。

四、当然还有一种比较难理解的差分做法,说起来比较麻烦。。也比较蛋疼。。绕两下就绕晕了。但是不知道怎么回事COGS上的大神们都是这么做的,这里就不推荐了。

扫描左端点:

#include
using namespace std;
#include
#include
#include
#include
#define root 1,1,N
#define lson node<<1,l,(l+r)>>1
#define rson node<<1|1,((l+r)>>1)+1,r
char * ptr=(char *)malloc(10000000);
int pp[1000001],tree[200000],ans[200000];
struct S{
	int l,r,i;
	inline bool operator < (S a)const{
		return l'9')++ptr;
	x=0;
	while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0';
}
inline void add(int node,int l,int r,int a,int x){
	if(l==r)tree[node]+=x;
	else{
		if(((l+r)>>1)r||b

扫描右端点:

#include
using namespace std;
#include
#include
#include
#include
char * ptr=(char *)malloc(3000000);
struct QS{
	int l,r,i;
	inline bool operator < (QS a)const{
		return r'9')++ptr;
	x=0;
	while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0';
}
int main(){
	freopen("diff.in","r",stdin);
	freopen("diff.out","w",stdout);
	fread(ptr,1,3000000,stdin);
	in(N);
	int i,j,now,M,x,get;
	for(i=1,++N;i


总结:

①离线处理询问区间时不仅可以扫左端点,也可以扫右端点。

②优化输出时开一个辅助小数组以做到逆序。

你可能感兴趣的:(线段树,BIT)