假设选手a的罚时为
t
a
1
,
t
a
2
t_{a1},t_{a2}
ta1,ta2,选手b的罚时为
t
b
1
,
t
b
2
t_{b1},t_{b2}
tb1,tb2,我们假设让a选手来做第1题会更优,也就是说:
t
a
1
+
t
b
2
−
(
t
a
2
+
t
b
1
)
>
0
t_{a1}+t_{b2}-(t_{a2}+t_{b1})>0
ta1+tb2−(ta2+tb1)>0 也也就是说说:
t
a
1
−
t
a
2
>
t
b
1
−
t
b
2
t_{a1}-t_{a2}>t_{b1}-t_{b2}
ta1−ta2>tb1−tb2 这意味着,我们按着
t
1
−
t
2
t_1-t_2
t1−t2来排个序就能确定谁应该更优先做第一题了。然后前缀后缀搞一搞就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
const long long maxn=3*1e5+9;
long long n,m;
struct Node{
long long index;
long long one,two;
}nds[maxn];
long long score_one[maxn];
long long score_two[maxn];
vector<long long> ban[maxn];
long long ans[maxn];
long long suf[maxn];
int main() {
#ifdef LOCAL_DEBUG
freopen("in.txt","r",stdin);
#endif // LOCAL_DEBUG
cin>>n>>m;
for(long long i=1;i<=n;i++) {
scanf("%lld%lld",&nds[i].one,&nds[i].two);
nds[i].index=i;
score_one[i]=nds[i].one;
score_two[i]=nds[i].two;
}
long long a,b;
for(long long i=0;i<m;i++) {
scanf("%lld%lld",&a,&b);
ban[a].push_back(b);
ban[b].push_back(a);
}
sort(nds+1,nds+1+n,[](Node a,Node b){return a.one-a.two<b.one-b.two;});
for(long long i=n;i>=1;i--) suf[i]=suf[i+1]+nds[i].two;
set<long long> show;
long long pre=0;
for(long long i=1;i<=n;i++) {
long long index=nds[i].index;
ans[index]+=pre; //第一题别人写
show.insert(index);
ans[index]+=(i-1)*nds[i].two; //第二题自己写
ans[index]+=suf[i+1];
ans[index]+=nds[i].one*(n-i);
long long cnt=0;
for(long long j=0;j<ban[index].size();j++) {
if(show.count(ban[index][j])) {
cnt++;
ans[index]-=score_one[ban[index][j]];
ans[index]-=score_two[index];
}
else {
ans[index]-=score_two[ban[index][j]];
ans[index]-=score_one[index];
}
}
pre+=nds[i].one;
}
for(long long i=1;i<=n;i++) {
printf("%lld ",ans[i]);
}
putchar(10);
}