思路:定义两棵树状数组,第一个记录坐标个数和,第二个记录横坐标和。
对volumn从小到大排序,保证遍历更新的时候当前的volumn取最大。
lescnt表示前i-1个比第i个横坐标小的cow的总数。
lessum表示前i-1个横坐标比当前小的横坐标之和
bigcnt表示前i-1个比当前横坐标大的cow的总数,当然等于i-1-lescnt了
bigsum表示前i-1个比当前横坐标大的横坐标之和,当然等于sumx-lesssum了
然后更新ans+=a[i].v*(lescnt*a[i].x-lessum+bigsum-bigcnt*a[i].x);
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
#define LL long long
const int maxn=20005;
LL c[2][maxn];
int n;
struct node{
int v,x;
}a[maxn];
void add(int x,int id,int val)
{
while(x<=maxn)
{
c[id][x]+=val;
x+=(x&-x);
}
}
LL sum(int x,int id)
{
LL s=0;
while(x>0)
{
s+=c[id][x];
x-=(x&-x);
}
return s;
}
bool cmp(node a,node b)
{
return a.v<b.v;
}
int main()
{
LL lescnt,lessum,bigcnt,bigsum,sumx;
int i;
while(~scanf("%d",&n))
{
memset(c,0,sizeof(c));
LL ans=0;
for(i=1;i<=n;++i)
scanf("%d%d",&a[i].v,&a[i].x);
sort(a+1,a+1+n,cmp);
add(a[1].x,0,1);
add(a[1].x,1,a[1].x);
sumx=a[1].x;
for(i=2;i<=n;++i)
{
lescnt=sum(a[i].x,0);
lessum=sum(a[i].x,1);
bigcnt=i-1-lescnt;
bigsum=sumx-lessum;
ans=ans+a[i].v*(lescnt*a[i].x-lessum+bigsum-bigcnt*a[i].x);
add(a[i].x,0,1);
add(a[i].x,1,a[i].x);
sumx+=a[i].x;
}
printf("%I64d\n",ans);
}
return 0;
}