题意:
有n个参赛者,每个参赛者在做第一题和第二题都有一个罚时,两个人组成一队,每个人负责一题,该队罚时为两人罚时之和(队内会取最优策略),求该参赛者在所有可能的组队中总罚时为多少?

思路:
我们发现可以按照前一个写第一题,后一个写第二题最优来排序:
既:A.a+B.b<A.b+B.a
先求该参赛者与所有其他参赛者组队的总贡献:
既:与排在自己前面的组队时取前面的第一题罚时,自己取第二题罚时。
与排在自己后面的组队时取后面的第二题罚时,自己取第一题罚时。
这过程可以用前缀和优化。
然后由于某些不能组队,所有将不能组队的贡献减去即可。

代码:

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <iostream>

using namespace std;

typedef long long ll;
const ll inf=1e9+9;
const int N=1000005;

struct w
{
    ll a, b, k;
}w[N];

bool cmp(struct w a,struct w b)   // 排序规则
{
    return a.a+b.b<a.b+b.a;
}

ll suma[N], sumb[N], ans[N];

int main()
{
    ll n, m;
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld%lld",&w[i].a,&w[i].b);
        w[i].k=i;
    }
    for(int i=1;i<=m;i++)   //减去不能组队的队伍的贡献。
    {
        int x, y;
        scanf("%d%d",&x,&y);
        ll k=min(w[x].a+w[y].b,w[x].b+w[y].a);
        ans[x]-=k;
        ans[y]-=k;
    }
    sort(w+1,w+n+1,cmp);
    for(int i=1;i<=n;i++)   //求前缀和
    {
        suma[i]=suma[i-1]+w[i].a;
        sumb[i]=sumb[i-1]+w[i].b;
    }
    for(int i=1;i<=n;i++)    //加上所有队伍的贡献。
    {
        ans[w[i].k]+=suma[i-1]+(i-1)*w[i].b+sumb[n]-sumb[i]+(n-i)*w[i].a;
    }
    for(int i=1;i<=n;i++)
    {
        printf("%lld%c",ans[i],i==n?'\n':' ');
    }
    return 0;
}