2022-04-05 21:57阅读: 28评论: 0推荐: 0

CF 730 A.Toda 2

A. Toda 2

题目大意

给定一个长度为n的数组。每次操作可以选择2到5个数,是其减一,如果该数为0则不变。最终所有数相等。问这个相等的最大值是多少。注意操作数不得大于 104n100,0ai100

解题思路

注意到就算每次选一个数是其减一,最后全部减到0所需要的操作数也刚好是104。因此这个操作数上限无需考虑。

注意到每次选择4个数可以拆成两次选择两个数,选择5个数可以拆成一次选择两个数和一次选择三个数。因此这两种选法无需考虑,只需考虑选择2个数和3个数的。

一个直观的想法就是,令目标数val为当前最小的数,然后每次选择最大的两个数,是其减一。直到剩下一个数不是val,看看它减到val的次数能不能插到之前的操作里(注意之前的操作该数不能减一),可以的话就可行,不行的话就令 val减一,重复上述步骤。

由于最多104次操作,用堆模拟这个过程即可。用 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;
}


本文作者:~Lanly~

本文链接:https://www.cnblogs.com/Lanly/p/16104164.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   ~Lanly~  阅读(28)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.