拿到题我们只需要考虑v比这个数小的就可以了,ans = Σv [i] * 比这个数小的点到这个数的距离之和。
那么这个距离之和怎么求呢?对于第 i 个数来说,
设 front [ i ] 表示v[ j ] 比v [ i ] 小且 x[ j ] 比x[ i ] 小的 j 的个数,这些数的x 之和为tot;
设sum为所有数中 v[ j ] 比v[ i ] 小的 j 的x 之和,cnt 为所有数中v比这个数小的个数。
比这个数小的点到这个数的距离之和 = front[ i ]*v[ i ] - tot +sum-tot-[v-front[ i ]]*x[ i ],这一部分为了简便,可以先对v从小到大排序;
不好理解,手动一下;
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
ll n;
struct node
{
ll v,x;
}edge[25000];
ll cmp(node a,node b)
{
if(a.v==b.v)
{
return a.x<b.x;
}
return a.v<b.v;
}
ll lowbit(ll a)
{
return a&(-a);
}
ll f[2][25000];
void add(ll p,ll a,ll d)
{
while(p<=20000)
{
f[d][p]+=a;
p+=lowbit(p);
}
return ;
}
ll sum(ll p,ll d)
{
ll num=0;
while(p)
{
num+=f[d][p];
p-=lowbit(p);
}
return num;
}
int main()
{
scanf("%lld",&n);
for(ll i=1;i<=n;i++)
{
scanf("%lld %lld",&edge[i].v,&edge[i].x);
}
sort(edge+1,edge+1+n,cmp);
ll ans=0;
for(ll i=1;i<=n;i++)
{
ll a=sum(edge[i].x,0);
ll b=sum(edge[i].x,1);
ans+=(edge[i].x*a-b+sum(20000,1)-b-(i-1-a)*edge[i].x)*edge[i].v;
add(edge[i].x,1,0);
add(edge[i].x,edge[i].x,1);
}
printf("%lld",ans);
}