By 三石吖 2026.2
4.贪心算法
11091 最优自然数分解问题
(1)容易想到肯定是先拆成连续的自然数,然后如果有剩余就按照从大到小的顺序给已经选中的数
(2)看提示做的,很困难啊
- 时间复杂度
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void get1(int n){
std::vector<int>a;
for(int i = 2; i <= n; i++){
a.push_back(i);
n -= i;
}
if(n){
for(int i = a.size() - 1; i >= 0 && n; i--){
a[i]++;
n--;
}
}
i64 res = 1;
for(auto c : a){
res *= c;
}
std::cout << res << " ";
}
void get2(int n){
i64 res2 = 1;
while(n >= 3){
res2 *= 3;
n -= 3;
}
if(n == 1){
res2 = res2 / 3 * 4;
}
while(n >= 2){
res2 *= 2;
n -= 2;
}
std::cout << res2 << "\n";
}
void solve(){
int n;
std::cin >> n;
if(n <= 2){
std::cout << n << " " << n << "\n";
return;
}else if(n == 3){
std::cout << 2 << " " << 3 << "\n";
return;
}
get1(n), get2(n);
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/
8598 整除15问题
不想重写了,就是讨论讨论判判判
端了个去年十月写的版本上来
- 时间复杂度:
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void solve(){
std::string s;
std::cin >> s;
std::vector<int>cnt(10, 0);
i64 sum = 0;
for(auto c : s){
cnt[c - '0']++;
sum += (c - '0');
}
if(sum % 3 == 2){
for(int i = 2; sum % 3 && i <= 9; i += 3){
if(i == 5 && cnt[i] == 1 && !cnt[0]){
continue;
}
if(cnt[i]){
cnt[i]--;
sum -= i;
}
}
for(int i = 1; sum % 3 && i <= 9; i += 3){
while(cnt[i] && sum % 3){
cnt[i]--;
sum -= i;
}
}
}else if(sum % 3 == 1){
for(int i = 1; sum % 3 && i <= 9; i += 3){
if(cnt[i]){
cnt[i]--;
sum -= i;
}
}
for(int i = 2; sum % 3 && i<= 9; i += 3){
while(cnt[i] && sum % 3){
if(i == 5 && cnt[i] == 1 && !cnt[0]){
break;
}
cnt[i]--;
sum -= i;
}
}
}
if(sum % 3 || count(cnt.begin(), cnt.end(), 0)==10 || (!cnt[0] && !cnt[5])){
std::cout << "impossible\n";
}else{
if(cnt[0]){
for(int i = 9; i >= 0; i--){
for(int j = 0; j < cnt[i]; j++){
std::cout << i;
}
}
}else{
for(int i = 9; i >= 0; i--){
for(int j = 0; j < (i == 5 ? cnt[i] - 1:cnt[i]); j++){
std::cout << i;
}
}
std::cout << 5;
}
std::cout << "\n";
}
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/
8602 区间相交问题
按右边界排序,数有多少个不重的区间
- 时间复杂度
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void solve(){
int n;
std::cin >> n;
std::vector<pii>a(n);
for(int i = 0; i < n; i++){
std::cin >> a[i].second >> a[i].first;
}
std::sort(a.begin(), a.end());
int end = -inf;
int cnt = 0;
for(int i = 0; i < n; i++){
if(a[i].second >= end){
cnt++;
end = a[i].first;
}
}
std::cout << n - cnt << "\n";
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/
8605 删数问题
暴力跑轮,每轮从高位往低位贪心,删第一个减小的位置
- 时间复杂度
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void solve(){
std::string s;
int k;
while(1){
std::cin >> s;
if(s == "0"){
break;
}
std::cin >> k;
for(int i = 0; i < k; i++){
int mx = s[0] - '0';
int inx = 0;
int n = s.size();
for(int j = 1; j < n; j++){
if(s[j] - '0' < mx) {
break;
}
mx = s[j] - '0';
inx = j;
}
s.erase(s.begin() + inx);
}
std::cout << s << "\n";
}
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/
10346 带限期和价值的作业安排问题
按价值排序,然后记录一下有没有用过这个时间点
- 时间复杂度
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void solve(){
int n;
std::cin >> n;
std::vector<std::vector<int>>a(n, std::vector<int>(2));
for(int i = 0; i < n; i++){
std::cin >> a[i][0];
}
for(int i = 0; i < n; i++){
std::cin >> a[i][1];
}
std::sort(a.begin(), a.end(), [](const std::vector<int> &x, const std::vector<int> &y){
return x[1] > y[1];
});
std::map<int, int>vis;
int ans = 0;
for(int i = 0; i < n; i++){
if(vis[a[i][0]]){
continue;
}
vis[a[i][0]] = 1;
ans += a[i][1];
}
std::cout << ans << "\n";
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/
11079 可以移动的石子合并
(1)最高得分就是每次选最大的两堆,可以直接算数学关系
(2)最小得分就是每次选最小的堆,用小根堆模拟即可
- 时间复杂度
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void solve(){
int n, k;
std::cin >> n >> k;
std::vector<int>a(n);
std::priority_queue<int, std::vector<int>, std::greater<>>que;
for(int i = 0; i < n; i++){
std::cin >> a[i];
que.push(a[i]);
}
std::sort(a.begin(), a.end(), std::greater<>());
i64 max = 1LL * (n - 1) * a[0], min = 0;
for(int i = 1; i < n; i++){
max += 1LL * (n - i) * a[i];
}
while(n % (k - 1) != 1){
que.push(0);
n++;
}
while(que.size() > 1){
i64 cur=0;
int siz = que.size();
for(int i = 0; i < std::min(k, siz); i++){
cur += que.top();
que.pop();
}
min += cur;
que.push(cur);
}
std::cout << min << " " << max << "\n";
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/
17964 水桶打水
按时间从小到大排序, 要让等待时间短,优先放打的快的,每次放入都选等待时间最短的那个水龙头,然后用小顶堆模拟
- 时间复杂度
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void solve(){
int n, r;
std::cin >> n >> r;
std::vector<int>t(n);
for(int i = 0; i < n; i++){
std::cin >> t[i];
}
std::sort(t.begin(), t.end());
std::priority_queue<int, std::vector<int>, std::greater<>>que;
for(int i = 0; i < r; i++){
que.push(0);
}
int ans = 0;
for(int i = 0; i < n; i++){
int x = que.top();
que.pop();
que.push(x + t[i]);
ans += x + t[i];
}
std::cout << ans << "\n";
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/
17103 基站建设
发现一个基站可以影响公里,那么排序后按长度为分块即可
- 时间复杂度
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void solve(){
int n;
std::cin >> n;
std::vector<int>a(n);
for(int i = 0; i < n; i++){
std::cin >> a[i];
}
std::sort(a.begin(), a.end());
int ans = 0;
for(int i = 0, j; i < n; i = j){
ans++;
j = i + 1;
while(j < n && a[j] - a[i] <= 8){
j++;
}
}
std::cout<<ans<<"\n";
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/