E. Train Hard, Win Easy
题解:考虑 i i i和 j j j一起打时,如果 i i i打第一道, j j j打第二道,就有 a i + b j < a j + b i a_i+b_j <a_j + b_i ai+bj<aj+bi,所以可得 a i − b i < a j − b j a_i-b_i <a_j - b_j ai−bi<aj−bj,因此我们只需要根据 a i − b i a_i - b_i ai−bi排序并同时记录 i i i的位置,然后做个前缀和。最后枚举第i种情况,去减去 m i n ( x u + y v , x v + y u ) min(x_u + y_v,x_v + y_u) min(xu + yv,xv + yu) 即可。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define PII pair <int,int>
const int N = 3E5+10;
int n,m,x[N],y[N];
PII diff[N];
int place[N],u,v;
vector<int> G[N];
LL ans[N], pre[N], suf[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; ++i) {
scanf("%d %d",&x[i],&y[i]);
diff[i] = {y[i] - x[i],i};
}
for(int i = 1; i <= m; ++i) {
scanf("%d %d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
sort(diff+1,diff+n+1);
for(int i = 1; i <= n; ++i) {
pre[i] = pre[i - 1] + y[diff[i].second];
}
for(int i = n; i >= 1; --i) {
suf[i] = suf[i + 1] + x[diff[i].second];
}
for(int i = 1; i <= n; ++i) {
int u = diff[i].second;
LL ret = pre[i - 1] + suf[i + 1] + 1LL * (i - 1) * x[u] + 1LL * (n - i) * y[u];
for(int v : G[u])
ret -= min(x[u] + y[v], x[v] + y[u]);
ans[u] = ret;
}
for(int i = 1; i <= n; ++i)
printf("%lld%c",ans[i],i==n?'\n':' ');
return 0;
}