传送门:https://codeforces.com/problemset/problem/134/C
关注到题目的两个限制:1. 一个人只能与另外同一人交换一张卡牌。2. 一个人只能交换自己原来颜色的卡牌。
对于2条限制条件,显然有贪心思路:尽量让更多的人手持原有的卡牌。对于当前待交换的卡牌,一种构造思路,我们每次贪心选取手中拥有原有牌最多的人进行交换是最优的。
因为如果一个人手中原有的牌被取完就无法与其他人进行交换,显然比从拥有更多原有牌中取更劣。
此过程可以用大根堆维护,当一个人需要交换的卡牌比堆内剩余人数更多则不合法(为满足限制1)。
总时间复杂度 \(O((n+s)log_{2}n)\) 。
#include <bits/stdc++.h>
using namespace std;
inline int read() {
char c;
bool flag = false;
while ((c = getchar()) < '0' || c > '9') if (c == '-') flag = true;
int res = c - '0';
while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + c - '0';
return flag ? -res : res;
}
const int _ = 2e5 + 1;
struct Node {
int val, id;
bool operator<(const Node &o) const { return val < o.val; }
} a[_];
vector<pair<int, int>> ans;
int main() {
int n = read(), s = read();
priority_queue<Node> q;
for (int i = 1; i <= n; ++i) {
a[i].val = read(), a[i].id = i;
if (a[i].val) q.push(a[i]);
}
while (!q.empty()) {
Node o = q.top();
q.pop();
if (o.val > q.size()) {
puts("No");
return 0;
}
vector<Node> tmp;
while (o.val) {
Node y = q.top();
q.pop();
ans.push_back(make_pair(y.id, o.id));
--o.val;
--y.val;
if (y.val) tmp.push_back(y);
}
for (Node k: tmp) q.push(k);
}
puts("Yes");
printf("%zu\n", ans.size());
for (auto p: ans) printf("%d %d\n", p.first, p.second);
return 0;
}
标签:val,int,题解,交换,卡牌,read,CF131C,ans
From: https://www.cnblogs.com/Jefferyz/p/18450545