每年,农夫约翰的N(1 <= N <= 20,000)只牛会参加“MooFest”,一个来自世界各地的牛的社交聚会。 MooFest有许多活动,包括干草堆积,篱笆跳跃,把尾巴钉在农夫的身上...当奶牛都站在同一个地方排队,他们会大声喊叫,吼声几乎震耳欲聋。事实上,每年参加了这个活动后,一些奶牛已经失去了部分听力。 

每个奶牛具有耳背值v(i)(在1..20,000的范围内)。如果一头牛向牛i吼叫,她必须使用至少是两头母牛之间距离的v(i)倍的声音,以便被牛i听到。如果两个奶牛i和j想要交谈,她们必须以等于她们之间的距离乘以max(v(i),v(j))的音量说话。 

假设N头奶牛中的每头奶牛都站在直线上(每头奶牛在1..20,000范围内的某个独特x坐标),每对奶牛都使用尽可能小的声音进行谈话。 

计算所有N(N-1)/ 2对正在说话的奶牛产生的所有声音的总和。 
Input
*第1行:单个整数,N 

*第2到N + 1行:两个整数:牛的耳背值v和x坐标。第2行代表第一头牛;第3行表示第二头牛;等等。没有两头牛会站在同一个位置。 
Output
*第1行:仅含单个整数,表示所有牛互相吼叫的所有声音的总和。 
Sample Input
4
3 1
2 5
2 6
4 3
Sample Output
57

 

思路:当两头牛进行计算时,用到的是V值大的牛。所以先按照V值从大到小排序,当计算某头牛时,只考虑V值比它小的那些牛。我们用两个树状数组分别表示牛的坐标之和及牛的数量之和(以坐标作为数组下标)。那么考虑牛i时(按V从大到小排序后),设坐标值比它小的那些牛的数目为num1、坐标之和为sum1,坐标值比它大的那些牛的数目为num2、坐标之和为sum2,那么对该牛而言(设坐标为X,体力值为V),所贡献的答案为V * ( X*num1-sum1 + sum2-X*num2 )。

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>


#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int  MAXN = 2e5+5;

struct Node{
    int x;
    int val;
};

int c1[MAXN],c2[MAXN];
Node a[MAXN];
int n;



bool cmp(Node a,Node b)
{
    return a.val>b.val;
}

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

void updata(int a[],int x,int v)
{
    while (x<MAXN)
    {
        a[x] += v;
        x += lowbit(x);
    }
}

int getsum(int a[],int x)
{
    int res = 0;
    while (x)
    {
        res += a[x];
        x -= lowbit(x);
    }
    return res;
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i].val,&a[i].x);
        updata(c1,a[i].x,a[i].x);
        updata(c2,a[i].x,1);
    }
    sort(a+1,a+1+n,cmp);
    LL ans = 0;
    for (int i=1;i<=n;i++)
    {
        updata(c1,a[i].x,-a[i].x);
        updata(c2,a[i].x,-1);
        int sum1 = getsum(c1,a[i].x);
        int sum2 = getsum(c1,MAXN)-sum1;
        int num1 = getsum(c2,a[i].x);
        int num2 = getsum(c2,MAXN)-num1;
        ans += (LL)(abs(a[i].x*num1-sum1)+abs(sum2-a[i].x*num2))*a[i].val;
    }
    printf("%lld\n",ans);
    return 0;
}