codeforces 1043 E. Train Hard, Win Easy

题目
传送门

题意:
有n个人,m个排斥关系,有一个竞赛,有两道题目,给出n个人做两道题的做题速度,然后求分别这n个人做题时间累积的最小值。每个人只能做一道题,下一个题目必须他的同伴来做。有排斥关系的两个人不能相互组队。

思路:
设i的做题时间分别为xi,yi,j的做题时间分别为xj,yj。

若让i做第一题,j做第二题,则必须满足以下不等式:

xi+yj<xj+yi; 则 xi-yi<xj-yj, 只要是满足xj-yj>xi-yi的形式一定是i做第一题。

同理,i做第二题,j做第一题也是一样的做法。

然后再减去相互排斥的人就可以了。

代码如下:
 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=3*1e5+5;
int n,m;
struct score
{
    ll a,b,t;
    int id;
};
score a[maxn],b[maxn];
int loc[maxn];
ll suma[maxn],sumb[maxn];
ll Min[maxn];
vector<int>v[maxn];
int compare (score a,score b)
{
    return a.t<b.t;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%lld%lld",&a[i].a,&a[i].b);
        a[i].t=a[i].a-a[i].b;
        a[i].id=i;
        b[i]=a[i];
    }
    sort (a+1,a+n+1,compare);
    suma[0]=0; sumb[0]=0;
    for (int i=1;i<=n;i++)
    {
        suma[i]=suma[i-1]+a[i].a;
        sumb[i]=sumb[i-1]+a[i].b;
    }
    for (int i=1;i<=n;i++)
    {
        ll temp1=0,temp2=0,temp=0;
        temp1=sumb[n]-sumb[i]+(n-i)*a[i].a;
        temp2=suma[i-1]+(i-1)*a[i].b;
        Min[a[i].id]=temp1+temp2;
    }
    for (int i=0;i<m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        ll t=min(b[x].a+b[y].b,b[x].b+b[y].a);
        Min[x]-=t;
        Min[y]-=t;
    }
    for (int i=1;i<=n;i++)
    {
        printf("%lld%c",Min[i],i==n?'\n':' ');
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/84247975