NFLS贪心与数据结构题单笔记(未完结)
A. 奶牛飞车
贪心,把最慢的放前面
#include <bits/stdc++.h>
using namespace std;
constexpr int maxn = 1e6 + 10;
int n, m, d, L;
int s[maxn];
int ans = 0;
inline bool cmp(int x, int y) { return x > y; }
int main() {
cin >> n >> m >> d >> L;
for (int i = 1; i <= n; i++) {
cin >> s[i];
}
sort(s + 1, s + 1 + n);
int num = 0;
for (int i = 0, j = 0; i < n; j++) {
if (j == m)
j = 0, num++;
i++;
while (s[i] - num * d < L) {
i++;
if (i > n) {
cout << ans << endl;
return 0;
}
}
ans++;
}
cout << ans << endl;
return 0;
}
B. 牛奶规划
Lay博士有N(1<=N<=10000)头奶牛准备吃草,每头牛都需要一个单位时间来吃草,且每一个时刻最多只能让一头牛吃草.牛i必须在小于等于di时刻才能吃草(1<=di<=10000)吃了草之后能产出gi(1<=gi<=1000)的奶.时间从t=1开始.
请帮助Lay博士求出最多能得到的牛奶数量.
按照牛奶的大小从大到小排序。
之后对于每一只奶牛,如果在他挤奶时间之前有空闲时间,则可以挤奶,否则换下一只奶牛。可以证明这样取到的牛奶量是最大的。
C. 集市班车
逛逛集市,兑兑奖品,看看节目对农夫约翰来说不算什么,可是他的奶牛们非常缺乏锻炼——如果要逛完一整天的集市,他们一定会筋疲力尽的。所以为了让奶牛们也能愉快地逛集市,约翰准备让奶牛们在集市上以车代步。但是,约翰木有钱,他租来的班车只能在集市上沿直线跑一次,而且只能停靠N 个地点(所有地点都以1到N之间的一个数字来表示)。现在奶牛们分成K 个小组,第 i 组有Mi (1 ≤ Mi ≤ N)头奶牛,他们希望从Si跑到Ti (1 ≤ Si < Ti ≤ N)。由于班车容量有限,可能载不下所有想乘车的奶牛们,此时也允许小组里的一部分奶牛分开乘坐班车。约翰经过调查得知班车的容量是C ,请你帮助约翰计划一个尽可能满足更多奶牛愿望的方案。
只有一间教室,要安排尽可能多的活动。
那么我们用一个变量t表示已安排最后一个活动的结束时间,赋初值为-1,按活动结束时间排序,依次接受,接受的时候注意判断,一定要该活动的开始时间>=上一个活动的结束时间。
说了这么多,我们来看这道题。
C的空间可以看作是共C间教室,那么我们就应该用一个数组来存储每一空间位置上奶牛的下车地点(每一间教室活动结束的时间)。贪心策略:同样按照结束时间排好,每一次上尽可能多的奶牛,上了之后,在对应空间位置上存放该奶牛的下车地点,当一只奶牛上车时,优先考虑与上一只奶牛时间点相近的(尽量使车可以坐满)
炸树
Byteotian Cave的结构是一棵N个节点的树,其中某些点上面已经安置了火咋药,现在需要点燃M个点上的引线引爆所有的火咋药。
某个点上的引线被点燃后的1单位时间内,在树上和它相邻的点的引线会被点燃。
如果一个有火咋药的点的引线被点燃,那么这个点上的火咋药会爆火咋。
求引爆所有火咋药的最短时间。
一眼二分答案,然后统计当前答案的最小火咋药需求数,我的假做法,打了n个补丁依旧从20分一路涨到了57分,三分三分的涨,没救了。
#include <bits/stdc++.h>
using namespace std;
constexpr int maxn = 4000000;
int n, m, B;
struct edge {
int to, next;
} e[maxn];
int cnt = 0;
int head[maxn];
int node[maxn], IN[maxn], OUT[maxn];
void addedge(int u, int v) {
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
OUT[u]++, IN[v]++;
}
int ans = 0;
int dfs(int x, int need, int fa) {
if (need == 0) {
ans = B;
return 0;
}
int res = 0;
if (node[x] == 1)
res = 1;
else
res = 0;
for (int i = head[x]; i; i = e[i].next) {
if (e[i].to != fa)
res = max(res, dfs(e[i].to, need, x) + 1);
}
if (res > need) {
ans++, res = -need;
}
return res;
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> node[i];
if (node[i] == 1) {
B++;
}
}
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
addedge(u, v);
addedge(v, u);
}
int l = 0, r = n;
int mid;
while (l < r) {
mid = (l + r) >> 1;
ans = 0;
dfs(1, mid, -1);
if (ans <= m) {
r = mid;
} else {
l = mid + 1;
}
}
cout << l << endl;
return 0;
}
归根到底统计答案还得用一个类似DP的东西,但是不算DP。
f[x]表示在x的子树内未被覆盖的与x距离最远的敏感词点距离,g[x]表示在x的子树内与x距离最近的点燃点距离。
如果f[x]+g[x]<=mid,那么就说明x子树内就可以搞定。
如果f[x]==mid,那么就说明x一定要被点燃。
剩下的情况就可以留给祖先处理。
漫长的征途
1、假设在能跑到的范围内,第一个价格比他便宜的加油站to,就在当前加油站加油,加到恰好能跑到to
2、在能跑到的范围内,没有价格比他便宜的加油站,就在now加满油,跑到能跑到的范围内,价格最便宜的加油站
注意,在1中不是跑到范围内最便宜的加油站,而是只要遇到一个比now便宜,就跑过去
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
int N, G, B, D;
void read(int &x) {
x = 0;
char c = getchar();
while (!isdigit(c)) c = getchar();
while (isdigit(c)) {
x = x * 10 + c - '0';
c = getchar();
}
}
struct node {
int d, p;
} e[50005];
int dis[50005], price[50005];
int findmin(int s, int lim) {
int now = s + 1, to = 50003;
while (now <= N) {
if (dis[now] - dis[s] > lim)
return to;
if (price[now] < price[s])
return now;
if (price[now] < price[to])
to = now;
now++;
}
return to;
}
inline bool cmp(node a, node b) { return a.d < b.d; }
signed main() {
cin >> N >> G >> B >> D;
for (int i = 1; i <= N; i++) cin >> e[i].d >> e[i].p;
sort(e + 1, e + N + 1, cmp);
for (int i = 1; i <= N; i++) {
dis[i] = e[i].d;
price[i] = e[i].p;
if (dis[i] - dis[i - 1] > G) {
cout << "-1";
return 0;
}
}
if (dis[1] > B || D - dis[N] > G) {
cout << "-1";
return 0;
}
price[50003] = 2e9;
int now = 0, to;
to = findmin(now, B);
if (now > N) {
cout << "0";
return 0;
}
now = to;
int nowB = B - dis[to];
int ans = 0;
if (dis[N] == D)
price[N] = 0;
else {
N++;
dis[N] = D;
price[N] = 0;
}
while (now < N) {
to = findmin(now, G);
if (price[to] > price[now]) {
ans += (G - nowB) * price[now];
nowB = G - dis[to] + dis[now];
} else {
ans += (dis[to] - dis[now] - nowB) * price[now];
nowB = 0;
}
now = to;
}
cout << ans << endl;
return 0;
}