标签:
题目链接:点击打开链接
解题思路:
1、首先对x和高度h分别从小到大排序记录排名
2、然后对高度h按从大到小排序(保证当前要计算的树的高度是所有已经遍历的树中最小高度,便于计算S=min(h1,h2))
3、循环遍历数组,每次遍历向树状数组C中t[i].rx位置增加t[i].rx,向树状数组C1中t[i].rx位置增加1
解析:C记录排名和,C1记录个数
所以以t[i].rh为最小值的点对的和为
t[i].rh*(sum(n)-sum(t[i].rx)-(LL)t[i].rx*(sum1(n)-sum1(t[i].rx))+(LL)sum1(t[i].rx-1)*t[i].rx-sum(t[i].rx-1));
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAXN 100010
using namespace std;
typedef unsigned long long LL;
struct tree{
int x;
int h;
int rx;
int rh;
}t[MAXN];
LL C[MAXN];
int C1[MAXN];
int rx,rh;
int n;
bool cmp1(tree a,tree b){
return a.x<b.x;
}
bool cmp2(tree a,tree b){
return a.h<b.h;
}
bool cmp3(tree a,tree b){
return a.h>b.h;
}
int lowbit(int x){
return x&(-x);
}
LL sum(int pos){
LL ret=0;
while(pos>0){
ret+=C[pos];
pos-=lowbit(pos);
}
return ret;
}
void add(int pos,int v){
while(pos<=n){
C[pos]+=v;
pos+=lowbit(pos);
}
}
int sum1(int pos){
int ret=0;
while(pos>0){
ret+=C1[pos];
pos-=lowbit(pos);
}
return ret;
}
void add1(int pos,int v){
while(pos<=n){
C1[pos]+=v;
pos+=lowbit(pos);
}
}
int main(){
while(scanf("%d",&n)!=EOF){
rx=rh=1;
for(int i=0;i<n;++i)
scanf("%d%d",&t[i].x,&t[i].h);
sort(t,t+n,cmp1);
t[0].rx=rx++;
for(int i=1;i<n;++i){
if(t[i].x==t[i-1].x)
t[i].rx=t[i-1].rx;
else
t[i].rx=rx;
rx++;
}
sort(t,t+n,cmp2);
t[0].rh=rh++;
for(int i=1;i<n;++i){
if(t[i].h==t[i-1].h)
t[i].rh=t[i-1].rh;
else
t[i].rh=rh;
rh++;
}
sort(t,t+n,cmp3);
memset(C,0,sizeof(C));
memset(C1,0,sizeof(C1));
LL ans=0;
for(int i=0;i<n;++i){
add(t[i].rx,t[i].rx);
add1(t[i].rx,1);
ans+=t[i].rh*(sum(n)-sum(t[i].rx)-(LL)t[i].rx*(sum1(n)-sum1(t[i].rx))+(LL)sum1(t[i].rx-1)*t[i].rx-sum(t[i].rx-1));
}
printf("%I64u\n",ans);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
hdu3015 Disharmony Trees(树状数组+排序)
标签:
原文地址:http://blog.csdn.net/mengxingyuanlove/article/details/47830597