zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    30天养成一个好习惯
    ym——安卓巴士总结了近百个Android优秀开源项
    内存泄漏以及常见的解决方法
    Android学习笔记(四十):Preference的使用
    Android中View绘制流程以及invalidate()等相关方法分析
    NumberFormat 类
    开发人员福利!ChromeSnifferPlus 插件正式登陆 Chrome Web Store
    memset函数具体说明
    分分钟教会你使用HTML写Web页面
    UVA 465 (13.08.02)
  • 原文地址:https://www.cnblogs.com/yuhan-blog/p/12308792.html
Copyright © 2011-2022 走看看