E. Train Hard, Win Easy

链接

[http://codeforces.com/contest/1043/problem/E]

题意

有n个人,每个人都有做出a,b题的分数,xi,yi,但是有些人是不能组队的,问你每个人和其他能组队的人最少分数和是多少
(组队时只能一个人做一个题,且不能相同)

分析

对于一个人和别人组队要么解决a,要么解决b, 他的分数是min(xi+yj,xj+yi);
所以我们只需要对统计xi+yj的情况和xj+yi的情况,若xi+yj<xj+yi 等价于xi-yi<xj-yj;
所以就对xi-yi;排序,后面就统计对其他人的分数最小和,最终减去不能组队的就是答案了具体看代码

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=3e5+10;
ll x[N],y[N];
ll ans[N];
int a[N];
vector<int> ve[N];
bool cmp(int b,int c){
	return x[b]-y[b]<x[c]-y[c];
}
int main(){
	int n,m,i,j;
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	//freopen("in.txt","r",stdin);
	 cin>>n>>m;
		int u,v;
		for(i=1;i<=n;i++){
			cin>>x[i]>>y[i];
			a[i]=i;
		}
		for(j=1;j<=m;j++)
		{
			cin>>u>>v;
			ve[u].push_back(v);
			ve[v].push_back(u);
		}
		sort(a+1,a+n+1,cmp);
		ll sum=0;
		for(i=1;i<=n;i++){
			ans[a[i]]=(i-1)*y[a[i]]+sum;
			sum+=x[a[i]];
		}
		sum=0;
		for(i=n;i>0;i--){
			ans[a[i]]+=(n-i)*x[a[i]]+sum;
			sum+=y[a[i]];
		}
		for(i=1;i<=n;i++)
			for(j=0;j<ve[i].size();j++)
			{
				ll Min=min(x[i]+y[ve[i][j]],x[ve[i][j]]+y[i]);
				ans[i]-=Min;
			}
		for(i=1;i<=n;i++)
		cout<<ans[i]<<' ';
		cout<<endl;
	return 0;
}
posted @ 2018-11-12 16:32  ChunhaoMo  阅读(200)  评论(0)    收藏  举报