牛客挑战赛52 A. 深海少女(贪心)
题目描述
现给定 n 个数 {ai}{ai} 和 m 个关系。
第 i 个关系形如 (x, y)。请你重排 {ai}{ai},使得 ∑i=1m(axi−ayi)i=1∑m(axi−ayi) 最小。
你只需要输出这个最小值即可。
输入描述:
一行两个数 n,m(1≤n,m≤105)n,m(1≤n,m≤105)。
第二行,n 个数,表示 {ai}i=1n(1≤ai≤109){ai}i=1n(1≤ai≤109)。
接下来 m 行,每行两个数 xi,yi(1≤xi,yi≤n)xi,yi(1≤xi,yi≤n)。
输出描述:
一行一个数,表示答案。
示例1
输入
复制
3 3
3 3 2
1 2
3 2
1 2
输出
复制
2
贪心。把\(\Sigma_{i=1}^n(a_{x_i}-a_{y_i})\)拆开为\(\Sigma_{i=1}^na_{x_i}-\Sigma_{i=1}^na_{y_i}\),这样就可以选择这么一种贪心策略:每个xi位置-1,每个yi位置+1,最后把a从大到小填充到值从大到小的每个位置即可。
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#define int long long
using namespace std;
int n, m, a[100005], ans[100005];
int cnt[100005];
struct node {
int id, cnt;
bool operator < (const node& o) const {
return cnt < o.cnt;
}
};
signed main() {
cin >> n >> m;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
sort(a + 1, a + n + 1);
memset(cnt, 0, sizeof(cnt));
vector<pair<int,int> > rel;
for(int i = 1; i <= m; i++) {
int x, y;
cin >> x >> y;
cnt[x]--;
cnt[y]++;
rel.push_back(make_pair(x, y));
}
vector<node> v;
for(int i = 1; i <= n; i++) {
node tmp;
tmp.id = i, tmp.cnt = cnt[i];
v.push_back(tmp);
}
sort(v.begin(), v.end());
for(int i = 0; i < v.size(); i++) {
ans[v[i].id] = a[i + 1];
}
int aans = 0;
for(auto x : rel) {
aans += ans[x.first] - ans[x.second];
}
cout << aans;
return 0;
}