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;elseres = 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,就在当前加油站加油,加到恰好能跑到to2、在能跑到的范围内,没有价格比他便宜的加油站,就在now加满油,跑到能跑到的范围内,价格最便宜的加油站注意,在1中不是跑到范围内最便宜的加油站,而是只要遇到一个比now便宜,就跑过去#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define int long longint 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;
}