先按照坐标x进行排序,随后用归并排序对v进行排序。用部分和去求总和。
#include<cstdio>
#include<cstdlib>
const int maxn=20002;
int v[maxn],x[maxn],n;
int b[maxn],c[maxn];
long long int ans;
void swap(int *a,int *b)
{
int tmp=*a;
*a=*b;
*b=tmp;
}
void sort(int l,int r)
{
int key=x[rand()%(r-l+1)+l];
int i=l,j=r;
while(i<=j)
{
while(x[i]>key)
i++;
while(x[j]<key)
j--;
if(i<=j)
{
swap(&x[i],&x[j]);
swap(&v[i],&v[j]);
i++;
j--;
}
}
if(l<j)
sort(l,j);
if(i<r)
sort(i,r);
}
void merge_sort(int l,int r)
{
if(l==r)
return;
int mid=(l+r)/2;
merge_sort(l,mid);
merge_sort(mid+1,r);
int p1=l,p2=mid+1;
int i=l;
long long int sum1=0,sum2=0;
for(int i=p1;i<=mid;i++)
{
sum1+=v[i];
}
for(int i=p2;i<=r;i++)
{
sum2+=v[i];
}
while(p1<=mid || p2<=r)
{
if((p2>r)||(p1<=mid&&v[p1]>v[p2]))
{
ans += v[p1] * ((r-p2+1)*x[p1] - sum2);
sum1-=v[p1];
c[i]=x[p1];
b[i++]=v[p1++];
}
else
{
ans+=v[p2]*((mid-p1+1)*x[p2]-sum1);
sum2-=v[p2];
c[i]=x[p2];
b[i++]=v[p2++];
}
}
for(int i=l;i<=r;i++)
{
x[i]=c[i];
v[i]=b[i];
}
}
int main()
{
srand(909978797);
freopen("moofest.in","r",stdin);
freopen("moofest.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&v[i],&x[i]);
}
sort(1,n);
merge_sort(1,n);
printf("%lld\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}