标签:
题目链接:点击打开链接
解题思路:
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