题意:
有若干棵树,每棵树有横坐标xi和高度hi。
把若干棵树按照x递增排序,每棵树的rank是ri,那么定义两颗树的F为abs(ri-rj)。
把若干棵树按照高度递增排序,每棵树的rank是ri,定义两棵树的D为min(ri,rj)。
两棵树的不和谐度定义为D * F。
求n棵树中任意两棵树的不和谐度的总和。
思路:
首先把每棵树的坐标rank和高度rank求出来。
然后按照高度rank降序排序,对于当前的树,小于等于它的x rank的树的数量可以用树状数组维护,它们的坐标rank总和也可以用树状数组维护。
假设前面所有树的x总和为dis,小于等于它的x rank的树的数量为cnt,它们的坐标rank总和为sum
那么Σabs(xi - xk)(k < i)的值就是cnt * xri - sum + dis - sum - (i - cnt - 1) * xri。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 const int N = 1e5 + 10; 6 int n; 7 int c[N]; 8 long long sum[N]; 9 struct node 10 { 11 int x,h; 12 int xr,hr; 13 } a[N]; 14 bool cmp1(node aa,node bb) 15 { 16 return aa.x < bb.x; 17 } 18 bool cmp2(node aa,node bb) 19 { 20 return aa.h < bb.h; 21 } 22 bool cmp3(node aa,node bb) 23 { 24 return aa.hr > bb.hr; 25 } 26 int lowbit(int x) 27 { 28 return x&(-x); 29 } 30 void addcnt(int x) 31 { 32 for (int i = x;i <= n;i += lowbit(i)) c[i]++; 33 } 34 void addsum(int x,int y) 35 { 36 for (int i = x;i <= n;i += lowbit(i)) sum[i] += y; 37 } 38 int getcnt(int x) 39 { 40 int ans = 0; 41 for (int i = x;i > 0;i -= lowbit(i)) ans += c[i]; 42 return ans; 43 } 44 long long getsum(int x) 45 { 46 long long ans = 0; 47 for (int i = x;i > 0; i-= lowbit(i)) ans += sum[i]; 48 return ans; 49 } 50 int main() 51 { 52 53 while (scanf("%d",&n) != EOF) 54 { 55 memset(c,0,sizeof(c)); 56 memset(sum,0,sizeof(sum)); 57 for (int i = 1;i <= n;i++) 58 { 59 scanf("%d%d",&a[i].x,&a[i].h); 60 } 61 sort(a+1,a+1+n,cmp1); 62 for (int i = 1;i <= n;i++) 63 { 64 if (i == 1) 65 { 66 a[i].xr = 1; 67 } 68 else 69 { 70 if (a[i].x == a[i-1].x) 71 { 72 a[i].xr = a[i-1].xr; 73 } 74 else 75 { 76 a[i].xr = i; 77 } 78 } 79 } 80 sort(a+1,a+1+n,cmp2); 81 for (int i = 1;i <= n;i++) 82 { 83 if (i == 1) 84 { 85 a[i].hr = 1; 86 } 87 else 88 { 89 if (a[i].h == a[i-1].h) 90 { 91 a[i].hr = a[i-1].hr; 92 } 93 else 94 { 95 a[i].hr = i; 96 } 97 } 98 } 99 sort(a+1,a+1+n,cmp3); 100 long long dis = 0; 101 long long ans = 0; 102 for (int i = 1;i <= n;i++) 103 { 104 int cnt = getcnt(a[i].xr); 105 long long su = getsum(a[i].xr); 106 long long res = 1LL * cnt * a[i].xr - su; 107 res += dis - su - 1LL * (i - cnt - 1) * a[i].xr; 108 ans += res * a[i].hr; 109 addcnt(a[i].xr); 110 addsum(a[i].xr,a[i].xr); 111 dis += a[i].xr; 112 113 } 114 printf("%lld ",ans); 115 } 116 return 0; 117 }