HDU 3015 Disharmony Trees(树状数组)

思路:

1.我们首先hashhash一下,计算出每棵树它的xxhh的排名,用pair<int,int>类型的数组存储每颗树,然后按hh的排名降序排列;
2.我们用降序排列好的数组,来一个个进行遍历;遍历之前我们应该先建好两个BITBIT,两个树状数组的计算函数(cal(i,1)cal(i,0),其中i代表位置,1代表第一个树状数组,0代表第二个树状数组)的意思分别为,已经遍历过的树中,xx小于ii的树的数量和andand这些树的xx总和;
3.每遍历到一颗树,我们计算这棵树和前面遍历过的每颗树的SFS*F总和,已知我们是倒序排列的hh,因此当前树的hh和前面遍历的树的hh相比一定是最小的,因此此时所有的SS都是这棵树的hh;接下来就需要计算所有SS的总和了,我们现在根据两个树状数组可以得到先前遍历过的树中,xx小于当前树的xx的树的数量(cal(x-1,0)),xx大于当前树的xx的树的数量(cal(n,0)-cal(x,0)),xx小于当前树的xx的树的所有xx总和(cal(x-1,1)),xx大于当前树的xx的树的所有xx总和(cal(n,1)-cal(x,1))(比较绕,请耐心理解),因此SS的总和计算公式就是cal(x-1,0)*x-cal(x-1,1)+(cal(n,1)-cal(x,1))-x*(cal(n,0)-cal(x,0))

代码:

#include<iostream>
#include<algorithm>
using namespace std;
template <class T>
inline bool read(T &ret){
	char c; int sgn;
	if(c=getchar(),c==EOF) return 0; //EOF
	while(c!='-'&&(c<'0'||c>'9')) c=getchar();
	sgn=(c=='-')?-1:1;
	ret=(c=='-')?0:(c-'0');
	while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
	ret*=sgn; return 1;
}
typedef long long LL;
typedef pair<int,int> pii;
#define fi first
#define sc second
#define mp(a,b) make_pair(a,b)
const int MAX_N=1e5+5;
pii tree[MAX_N];    //fi represents h;sc represents x
int n,x[MAX_N],h[MAX_N]; 
int sum[MAX_N],num[MAX_N];
int cal(int i,int type){  //type:1 calculate the array of sum //type:0 array of num
	int s=0;
	while(i>0) s+=(type?sum[i]:num[i]),i-=i&-i;
	return s;
}
void add(int i,int x,int type){
	while(i<=n){
		if(type) sum[i]+=x; else num[i]+=x;
		i+=i&-i;
	}
}
void init_hash(){
	int xx[MAX_N],hh[MAX_N],rank_x[MAX_N],rank_h[MAX_N];
	for(int i=0;i<n;i++) xx[i]=x[i],hh[i]=h[i];
	sort(xx,xx+n); sort(hh,hh+n);
	for(int i=0;i<n;i++){
		tree[i].fi=lower_bound(hh,hh+n,h[i])-hh+1;
		tree[i].sc=lower_bound(xx,xx+n,x[i])-xx+1;
	}
	sort(tree,tree+n,greater<pii>());
}
void solve(){
	LL ans=0;
	for(int i=0;i<n;i++){
		int x=tree[i].sc;
		LL S=1ll*tree[i].fi;
		LL F=1ll*(cal(x-1,0)*x-cal(x-1,1)+cal(n,1)-cal(x,1)-x*(cal(n,0)-cal(x,0)));
		ans+=S*F;
		add(x,1,0); add(x,x,1);
	}
	cout<<ans<<'
';
	for(int i=0;i<=n;i++) sum[i]=num[i]=0;
}
int main(){
	while(read(n)){
		for(int i=0;i<n;i++) read(x[i]),read(h[i]);
		init_hash(); solve();
	}
	return 0;
}
原文地址:https://www.cnblogs.com/yuhan-blog/p/12308792.html