题意:

有若干棵树,每棵树有横坐标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\n",ans);
115     }
116     return 0;
117 }

 

版权声明:本文为kickit原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/kickit/p/9077771.html