CF 730 A.Toda 2
A. Toda 2
题目大意
给定一个长度为\(n\)的数组。每次操作可以选择2到5个数,是其减一,如果该数为0则不变。最终所有数相等。问这个相等的最大值是多少。注意操作数不得大于 \(10^4\)。 \(n \leq 100, 0 \leq a_i \leq 100\)
解题思路
注意到就算每次选一个数是其减一,最后全部减到0所需要的操作数也刚好是\(10^4\)。因此这个操作数上限无需考虑。
注意到每次选择4个数可以拆成两次选择两个数,选择5个数可以拆成一次选择两个数和一次选择三个数。因此这两种选法无需考虑,只需考虑选择2个数和3个数的。
一个直观的想法就是,令目标数\(val\)为当前最小的数,然后每次选择最大的两个数,是其减一。直到剩下一个数不是val,看看它减到val的次数能不能插到之前的操作里(注意之前的操作该数不能减一),可以的话就可行,不行的话就令 \(val\)减一,重复上述步骤。
由于最多\(10^4\)次操作,用堆模拟这个过程即可。用 \(down\)数组记录有多少个操作某个数减一。
神奇的代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int n;
cin >> n;
priority_queue<pair<int, int>> tt;
int minn = 1e9 + 7;
for(int i = 0; i < n; ++ i){
int x;
cin >> x;
minn = min(minn, x);
tt.push({x, i});
}
vector<pair<int, int>> ans;
vector<int> down(n, 0);
int leff = 0;
int cc = 0;
while(tt.top().first != minn){
auto t1 = tt.top();
tt.pop();
auto t2 = tt.top();
tt.pop();
if (t2.first == minn){
if ((int)ans.size() - down[t1.second] >= t1.first - minn){
leff = t1.second;
cc = t1.first - minn;
break;
}else{
minn = max(minn - 1, 0);
}
}
ans.push_back({t1.second, t2.second});
down[t1.second] ++;
down[t2.second] ++;
t1.first = max(t1.first - 1, 0);
t2.first = max(t2.first - 1, 0);
tt.push(t1);
tt.push(t2);
}
cout << minn << '\n';
cout << ans.size() << '\n';
string s (n, '0');
for(auto i : ans){
s[i.first] = '1';
s[i.second] = '1';
if (i.first != leff && i.second != leff && cc)
s[leff] = '1';
cout << s << '\n';
s[i.first] = '0';
s[i.second] = '0';
if (i.first != leff && i.second != leff && cc){
s[leff] = '0';
-- cc;
}
}
return 0;
}