您的位置:首页 > 其它

HDU 3015 Disharmony Trees 【 树状数组 】

2015-06-30 13:24 363 查看
题意:给出n棵树,给出横坐标x,还有它们的高度h,先按照横坐标排序,则它们的横坐标记为xx,

再按照它们的高度排序,记为hh

两颗树的差异度为 abs(xx[i] - xx[j]) * min(hh[i],hh[j]),求所有的差异度的和

和上面一道题一样,只不过这题是要Min的值,就将h从大到小排序,保证每一个h都是当前最小的

然后维护比当前x小的坐标的个数,当前区间的总和,前面比x小的坐标的和

#include<iostream>
#include<cstdio>
#include<cstring>
#include <cmath>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
using namespace std;

typedef long long LL;
const int INF = (1<<30)-1;
const int mod=1000000007;
const int maxn=100005;

int n;
struct node{ int x,xx,h,hh,id;};

node a[maxn],b[maxn],q[maxn];
int c[maxn],d[maxn];
int s[maxn];

int cmp1(node n1,node n2){ return n1.x < n2.x; }
int cmp2(node n1,node n2){ return n1.h < n2.h;}
int cmp3(node n1,node n2){ return n1.h > n2.h;}

int lowbit(int x){ return x & (-x);}

LL sum(int c[],int x){
LL ret=0;
while(x>0){
ret+=c[x]; x-=lowbit(x);
}
return ret;
}

void add(int c[],int x,int d){
while(x < maxn){
c[x]+=d;x+=lowbit(x);
}
}

int main(){
while(scanf("%d",&n) != EOF){
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].h);

sort(a+1,a+n+1,cmp1);a[1].xx = 1;
for(int i=2;i<=n;i++){
if(a[i].x == a[i-1].x) a[i].xx = a[i-1].xx;
else a[i].xx = i;
}
sort(a+1,a+n+1,cmp2);a[1].hh = 1;
for(int i=2;i<=n;i++){
if(a[i].h != a[i-1].h) a[i].hh =i;
else a[i].hh = a[i-1].hh;
}
sort(a+1,a+n+1,cmp3);

//for(int i=1;i<=n;i++)
//printf("a[%d].x = %d a[%d].h = %d\n",i,a[i].xx,i,a[i].hh);

LL ans = 0;
for(int i=1;i<=n;i++){
LL x = sum(c,a[i].xx);
LL totalfront = sum(d,a[i].xx);
LL total = sum(d,maxn);
ans += a[i].hh * (x*a[i].xx - totalfront + total - totalfront - (i-x-1)*a[i].xx);
//    printf("x= %I64d  totalfront=%I64d total=%I64d  ans = %I64d\n",x,totalfront,total,ans);
add(c,a[i].xx,1);
add(d,a[i].xx,a[i].xx);
}
printf("%I64d\n",ans);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: