CodeForces

题目链接

题目大意

  给你n组数,每组数有a和b两个数,代表数量和让数量加1的花费,问让所有数量都不相同的最小代价。

解题思路

  如果直接贪心的话会发现情况很复杂。我们可以先求出所有数修改之后的数量应该是多少。如果两个数相同,那么其中一个数如果和其他数相同就得加到一个没有出现的数为止,不过有个更好的办法,对于这种情况,那么这几个数一定是连续的,所以可以先按a从小到大排序,如果之前的数字修改后,当前的数比他前一个数小,就让当前的数加1,设求出的数组为数组c。
  在得到数组c后,考虑如何用数组a转移到最后的数组b。设大于等于(a_i)(a_j)的最小的整数是(c_k),且(b_i>b_j),如果让(a_j)修改成(b_k),那么(a_i)就得修改成一个比x大的数,显然这样是不优的。所以需要优先使用b大的数字来修改。

代码

const int maxn = 2e5+10;
const int maxm = 1e6+10;

struct INFO {
	int x, y;
} info[maxn];
int n, arr[maxn];
int main() {
	cin >> n;
	for (int i = 1; i<=n; ++i) cin >> info[i].x, arr[i] = info[i].x;
	for (int i = 1; i<=n; ++i) cin >> info[i].y;
	sort(info+1, info+n+1, [](INFO a, INFO b) {return a.x<b.x;});
	for (int i = 1; i<=n; ++i) arr[i] = max(arr[i-1]+1, info[i].x);
	set<int> st;
	for (int i = 1; i<=n; ++i) st.insert(arr[i]);
	ll ans = 0;
	sort(info+1, info+n+1, [](INFO a, INFO b) {return a.y>b.y;});
	for (int i = 1; i<=n; ++i) {
		auto it = st.lower_bound(info[i].x);
		ans += 1LL*(*it-info[i].x)*info[i].y;
		st.erase(it);
	}
	cout << ans << endl;
	return 0;
}
原文地址:https://www.cnblogs.com/shuitiangong/p/14388106.html