6. 贪心
6.1 区间问题
题目:给定
思路:
贪心的想法是很显然的:先将所有区间按左端点排序。定义
- 若第
个区间被区间 包含,即 ,则将这两个区间合并,令 (相当于在区间 中选一个点)。 - 否则将
更新为 , 更新为 , 增加 。
最终的答案即为
这样,我们就可以让每个被选到的点都属于尽可能多的区间。时间复杂度
贪心思路的证明:
显然,上述贪心算法一定满足题目的要求。我们只需要证明
不妨设通过算法上述所得到点为
得证。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int, int> pii;
const int N = 1e5+10;
int n, cnt = 1;
pii a[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d%d", &a[i].first, &a[i].second);
sort(a+1, a+n+1);
int L = a[1].first, R = a[1].second;
for (int i = 2; i <= n; ++i) {
int L_ = a[i].first, R_ = a[i].second;
if (L <= L_ && L_ <= R) L = L_, R = min(R_, R);
else L = L_, R = R_, cnt ++;
}
printf("%d\n", cnt);
return 0;
}
题目:给定
思路:显然这道题与 AcWing 905. 区间选点 的答案是一模一样的。
题目:给定
思路:
题目可以转化为:计算出一个点最多被几个区间包含(因为这些区间一定不能分在一组)。
令
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int n, cnt = 0, ans;
int start[N], close[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d%d", &start[i], &close[i]);
sort(start+1, start+n+1), sort(close+1, close+n+1);
int i = 1, j = 1;
while (i <= n || j <= n) {
if (start[i] <= close[j] && i <= n) cnt ++, i ++;
else if (j <= n) cnt --, j ++;
ans = max(ans, cnt);
}
printf("%d\n", ans);
return 0;
}
题目:给定一个区间 -1
。
思路:
贪心算法:先将
- 找到第一个覆盖了
且右端点最大的区间(即 且 最大),所需区间增加 ,若找不到这样的区间,则无解; - 若
则说明已经找到答案,退出循环;否则令 。
证明比较显然,因为在剩下所有的能覆盖
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int, int> pii;
const int N = 1e5+10;
int n, s, t, ans;
bool check;
pii a[N];
int main() {
scanf("%d%d%d", &s, &t, &n);
for (int i = 1; i <= n; ++i) scanf("%d%d", &a[i].first, &a[i].second);
sort(a+1, a+n+1);
for (int i = 1; i <= n; ++i) {
int j = i, r = - 2e9;
while (j <= n && a[j].first <= s) r = max(r, a[j].second), j ++;
if (r < s) {ans = -1; break;}
ans ++;
if (r >= t) {check = 1; break;}
s = r;
i = j-1;
}
if (!check) ans = -1;
printf("%d\n", ans);
return 0;
}
6.2 Huffman 树
题目:有编号为
思路:合并果子是经典的 Huffman 树模型,其贪心思路很简单:每次取出两个最小值,将它们合并,直到只剩一堆石子。这个过程可以用小根堆实现,时间复杂度
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
int n, sum;
priority_queue<int, vector<int>, greater<int>> heap;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
int x; scanf("%d", &x);
heap.push(x);
}
while (heap.size() > 1) {
int a = heap.top(); heap.pop();
int b = heap.top(); heap.pop();
sum += a+b;
heap.push(a+b);
}
printf("%d\n", sum);
return 0;
}
6.3 排序不等式
题目:有
思路:
贪心思路:先将
证明:
假设我们将
得证。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int t; ll sum;
int a[N];
ll s[N];
int main() {
scanf("%d", &t);
for (int i = 1; i <= t; ++i) scanf("%d", &a[i]);
sort(a+1, a+t+1);
for (int i = 1; i <= t; ++i) {
s[i] = s[i-1]+a[i-1];
sum += s[i];
}
printf("%lld\n", sum);
return 0;
}
6.4 绝对值不等式
题目:在一条数轴上有
思路:
贪心思路:先将
证明:
我们先考虑只有
:题目所求为 ; :题目所求为 ; :题目所求为 。
显然当
类似地,只有
这两种情况可以推广至
得证。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int n, t, sum;
int a[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
sort(a+1, a+n+1);
t = a[n/2+1];
for (int i = 1; i <= n; ++i) sum += abs(t-a[i]);
printf("%d\n", sum);
return 0;
}
6.5 推公式
题目:有
思路:
考虑叠罗汉时相邻的两头奶牛
放在 上面:此时 ; 放在 上面:此时 。
考虑什么时候
那么当
我们可以将所有牛按
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 5e4+10;
int n;
ll ans = -1e18, sum;
pii c[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
int w, s; scanf("%d%d", &w, &s);
c[i].first = w+s, c[i].second = s;
}
sort(c+1, c+n+1);
for (int i = 1; i <= n; ++i) {
sum -= (ll)c[i].second;
ans = max(ans, sum);
sum += (ll)c[i].first;
}
printf("%lld\n", ans);
return 0;
}
本文作者:Jasper08
本文链接:https://www.cnblogs.com/Jasper08/p/17461503.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析