Codeforces Round #519 by Botan Investments-E. Train Hard, Win Easy
地址:http://codeforces.com/contest/1043/problem/E
思路:排序+前缀和。对于取min(s1+ss2,s2+ss1),当 s1+ss2<s2+ss1即s1-s2<ss1-ss2取 s1+ss2,因此可以按照 s1-s2由小到大排序,再求得s1的前缀和ps1[n]和s2的后缀和ps2[n]。求出全部队员与其他队员组合的总和,对于第i位的队员,sum=a[i].s1*(n-i)+a[i].s2*(i-1)+ps1[i-1]+ps2[i+1]。再减去m对互斥的队员即可
Code:
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
struct node{
int id;
LL s1;
LL s2;
LL x;
bool operator<(const node &p)const{
return x<p.x;
}
};
const int MAX_N=3e5+5;
const int MAX_M=3e5+5;
int n,m;
node a[MAX_N];
int d[MAX_M][2],p[MAX_N];
LL ps1[MAX_N],ps2[MAX_N];
LL res[MAX_N];
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;++i)
{
cin>>a[i].s1>>a[i].s2;
a[i].id=i;
a[i].x=a[i].s1-a[i].s2;
}
for(int i=0;i<m;++i)
cin>>d[i][0]>>d[i][1];
sort(a+1,a+n+1);
for(int i=1;i<=n;p[a[i].id]=i,++i)
ps1[i]=ps1[i-1]+a[i].s1;
for(int i=n;i>=1;--i)
ps2[i]=ps2[i+1]+a[i].s2;
for(int i=1;i<=n;++i)
res[a[i].id]=a[i].s1*(n-i)+a[i].s2*(i-1)+ps1[i-1]+ps2[i+1];
for(int i=0;i<m;++i)
{
int t1=p[d[i][0]],t2=p[d[i][1]];
LL ss=min(a[t1].s1+a[t2].s2,a[t1].s2+a[t2].s1);
res[d[i][0]]-=ss; res[d[i][1]]-=ss;
}
for(int i=1;i<n;++i)
cout<<res[i]<<" ";
cout<<res[n]<<endl;
return 0;
}