7.12
今天开始多校联合讲课了,第一天上的贪心,反正我一直觉得贪心是个挺玄学的东西;
因为前一天晚上没回学校睡的太晚了导致白天太困,听完课之后就回寝室睡觉了,睡到错过了午饭点。。。看来下次不能熬夜了,之后下午把题单的题目写了一些;
2021武汉ACM暑期集训——贪心
传送门
A. 爱与愁的心痛(洛谷_P1614)
传送门
数据很水,直接两层循环O(M x N)都能过;
#include <bits/stdc++.h>
#define ll long long
#define mms(a, b) memset(a, b, sizeof(a))
using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int MAX = 1e4 + 5;
int n, m;
int num[MAX];
void solve() {
int ans = INF;
for(int i = 0; i < n - m + 1; ++i) {
int sum = 0;
for(int j = 0; j < m; ++j) {
sum += num[i + j];
}
ans = min(ans, sum);
}
cout << ans << '\n';
}
void init() {
}
signed main() {
std::ios::sync_with_stdio(false);
/* cin.tie(nullptr);
cout.tie(nullptr); */
while(cin >> n >> m) {
for(int i = 0; i < n; ++i)
cin >> num[i];
solve();
}
}
WHUT的学长还提供了另外一个做法,一个类似于尺取法的做法,画一个长度为m的区间出来从数组头往数组尾滑动,滑动的实现是每次减去区间最前面一个数然后加上区间后第一个数,这样找出一个区间和最小的即为答案;
#include <bits/stdc++.h>
#define ll long long
#define mms(a, b) memset(a, b, sizeof(a))
using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int MAX = 1e4 + 5;
int n, m;
int num[MAX];
void solve() {
int sum = 0;
for(int i = 0; i < m; ++i)
sum += num[i];
int ans = sum;
for(int i = m; i < n; ++i) {
sum = sum - num[i - m] + num[i];
ans = min(ans, sum);
}
cout << ans << '\n';
}
void init() {
}
signed main() {
std::ios::sync_with_stdio(false);
/* cin.tie(nullptr);
cout.tie(nullptr); */
while(cin >> n >> m) {
for(int i = 0; i < n; ++i)
cin >> num[i];
solve();
}
}
B. 凌乱的yyy / 线段覆盖(洛谷_P1803)
传送门
经典贪心题了,贪心选择结束时间最早的;
#include <bits/stdc++.h>
#define ll long long
#define mms(a, b) memset(a, b, sizeof(a))
using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int MAX = 1e6 + 5;
int n;
struct Node {
int s, e;
}arr[MAX];
bool cmp(Node a, Node b) {
return a.e < b.e;
}
void solve() {
for(int i = 0; i < n; ++i) {
cin >> arr[i].s >> arr[i].e;
}
sort(arr, arr + n, cmp);
int now = -1, ans = 0;
for(int i = 0; i < n; ++i) {
if(arr[i].s >= now) {
ans++;
now = arr[i].e;
}
}
cout << ans << '\n';
}
void init() {
}
signed main() {
std::ios::sync_with_stdio(false);
while(cin >> n) {
solve();
}
}
C. 合并果子(洛谷_P1090)
传送门
每次选择最小的两个合并就行,但是这里每次合并后都要排序一次,所以会超时,这里用优先队列来实现排序;
#include <bits/stdc++.h>
#define ll long long
#define mms(a, b) memset(a, b, sizeof(a))
using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int MAX = 1e5 + 5;
int n;
void solve() {
priority_queue<int, vector<int>, greater<int> > q;
for(int i = 0; i < n; ++i) {
int num;
cin >> num;
q.push(num);
}
ll ans = 0;
while(q.size() > 1) {
ll tmp = q.top();
q.pop();
tmp += q.top();
q.pop();
ans += tmp;
q.push(tmp);
}
cout << ans << '\n';
}
void init() {
}
signed main() {
std::ios::sync_with_stdio(false);
while(cin >> n) {
solve();
}
}
今天腰格外的疼,疼到完全坐不住,所以最后只写了这么三个水题就回寝室贴药休息了,明天再把没做完的题补起来;