版权声明:若转载请附上原博客链接,谢谢! https://blog.csdn.net/Link_Ray/article/details/83550209
题意
每个人都可以解决A题和B题,得分分别是 和 ,他可以任意和他不讨厌的人组队,一个队伍中每个人都只能做 和 中的一道题,且每道题都只能由一个人来完成,队伍中两道题得分的总和越少越好。求出每个人所参与的所有队伍的得分总和。
题解
现在有c和d两个人组队,他们对于A题和B题的得分分别是, 和 。c可以做A题的条件是 。移项一下变成 。 所以我们可以按照每个人 进行排序,假设现在计算第i个人的得分,那么如果他和前 个人组队的话,他一直做的都是A题和后 个人组队的话做的都是B题。再分别求 和 的前缀和就可以做到 计算一个人的得分。最后再根据讨厌的关系减一减就可以了。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5+5;
struct node {
ll x,y;
int id;
ll val;
bool operator <(const node& rhs) const {
return val < rhs.val;
}
}a[maxn], b[maxn];
ll prex[maxn], prey[maxn];
ll ans[maxn];
int n,m;
ll get(ll x, ll _x, ll _y, int pos) {
ll px = pos;
// cout << px <<" ";
ll ret = 0;
ret += prey[px]+_x*px;
// cout << ret <<" ";
ret += prex[n]-prex[px]+_y*(n-px);
// cout << ret <<" ";
ret -= (_x+_y);
// cout << ret <<endl;
return ret;
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%lld%lld", &a[i].x, &a[i].y);
a[i].val = a[i].y-a[i].x;
b[i].x = a[i].x; b[i].y = a[i].y;
a[i].id = i;
}
sort(a+1,a+n+1);
// cout << a[4].val << endl;
for(int i = 1; i <= n; ++i) {
prex[i] = prex[i-1]+a[i].x;
prey[i] = prey[i-1]+a[i].y;
}
for(int i = 1; i <= n; ++i) {
// cout <<i <<" ";
ans[a[i].id] = get(a[i].y-a[i].x, a[i].x, a[i].y, i);
// cout << endl;
}
for(int i = 0; i < m; ++i) {
ll u,v;
scanf("%lld%lld", &u, &v);
ll ret = min(b[u].x+b[v].y, b[u].y+b[v].x);
// cout << ret << endl;
ans[u] -= ret;
ans[v] -= ret;
}
for(int i = 1; i <= n; ++i)
cout << ans[i] <<" ";
cout << endl;
return 0;
}