吐槽
这道题难在题意理解有木有。题目倒是不难。
题意搬运
给定 个人的两个属性 :
,并且给出了
个关系 :
表示第
个人不能和第
个人配对。
同时 二人规定配对的价值为 :
和
中的最小值。
现在你需要回答出每个人跟所有人配对(除开不能和自己匹配的人)的价值总和。
解题思路
那么考虑下面式子什么时候成立:
那么我们就得到:
这说明当 的时候我们应该用
去匹配
会得到最小价值。
否则的话我们就应该用 匹配
。
所以按照 从小到大排序,然后再使用前缀和优化即可,详见代码。
Code
有注释
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 3e5 + 50;
#define int long long
int n,m;
int start[MAXN],tot = 0;
int sum2[MAXN],sum[MAXN],Ans[MAXN],mp[MAXN];
inline int read() {
int x = 0 , flag = 1;
char ch = getchar();
for( ; ch > '9' || ch < '0' ; ch = getchar()) if(ch == '-') flag = -1;
for( ; ch >= '0' && ch <= '9' ; ch = getchar()) x = (x << 3) + (x << 1) + ch - '0';
return x * flag;
}
struct Node {
int x,y,id;
} P[MAXN];
struct Edge {
int next,to;
} edge[MAXN * 2];
void add(int u,int v) {
edge[++tot].next = start[u];
edge[tot].to = v;
start[u] = tot;
return ;
}
bool cmp(Node A, Node B) {
return (A.y - A.x) < (B.y - B.x);
}
signed main() {
n = read() , m = read();
for(int i = 1 ; i <= n ; i ++) P[i].x = read() , P[i].y = read() , P[i].id = i;
for(int i = 1 ; i <= m ; i ++) {
int u = read() , v = read();
add(u, v); add(v, u);
}
sort(P + 1 , P + 1 + n , cmp);
for(int i = 1 ; i <= n ; i ++) sum[i] = sum[i - 1] + P[i].y;
//上面这个就前缀和处理出了 Bj-Aj < Bi - Ai 的所有人的 B 之和
for(int i = n ; i >= 1 ; i --) sum2[i] = sum2[i + 1] + P[i].x;
//上面这个就前缀和处理出了 Bj-Aj > Bi - Ai 的所有人的 A 之和
for(int i = 1 ; i <= n ; i ++) mp[P[i].id] = i;
for(int i = 1 ; i <= n ; i ++) { //划重点,这个是计算答案的地方
Ans[P[i].id] += sum[i - 1] + (i - 1) * P[i].x;
// (i - 1) 就是 Bj-Aj < Bi - Ai 的所有人的个数,乘上 P[i].x 就表示用 Bi 去匹配
Ans[P[i].id] += sum2[i + 1] + (n - i) * P[i].y;
//这里同理
}
for(int j = 1 ; j <= n ; j ++) {
for(int i = start[j] ; i ; i = edge[i].next) {
int to = edge[i].to;
Ans[j] -= min(P[mp[j]].x + P[mp[to]].y , P[mp[j]].y + P[mp[to]].x);//暴力减去就行了
}
cout << Ans[j] << " ";
}
return 0;
} 
京公网安备 11010502036488号