CF #693 div3 做题记录
作者:互联网
主要是明天要考C语言上机,找一套CF div3拿C语言写一遍。
A
给一张$w*h$的纸,如果$w$(长)是偶数,那么就可以沿着剪开,变成两张$\frac{w}{2}*h$的纸,宽同理,问最后能不能得到(可以超过)$n$张纸。
剪到不能减,剪一次多一倍,就是看pow(2, $w$和$h$的因子$2$的个数)是不是超过$n$。
#include <stdio.h> typedef long long ll; int T, w, h; ll n; int main() { #ifndef ONLINE_JUDGE freopen("sample.in", "r", stdin); #endif for (scanf("%d", &T); T--; ) { scanf("%d%d%lld", &w, &h, &n); ll cnt = 1; for (; !(w & 1); w >>= 1, cnt <<= 1); for (; !(h & 1); h >>= 1, cnt <<= 1); if (cnt >= n) puts("YES"); else puts("NO"); } return 0; }
B
给了一堆糖,要么重量为1,要么重量为2,现在想要平均分成两堆(不能把2拆成1+1),问能不能做到。
总重量是确定的,而且必须是个偶数,然后就是考虑能否凑出总重量的一半。
发现1比2好用,所以先尽可能多用2,剩下用1补齐。
upd:貌似这个做法很鬼畜啊,只要按照奇偶讨论一下就好了。
#include <stdio.h> #define N 105 int T, n, a[N]; int min(int x, int y) { return x < y ? x : y; } int main() { #ifndef ONLINE_JUDGE freopen("sample.in", "r", stdin); #endif for (scanf("%d", &T); T--; ) { scanf("%d", &n); int sum = 0, cnt2 = 0; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); sum += a[i]; if (a[i] == 2) ++cnt2; } if (sum & 1) puts("NO"); else { sum >>= 1; int k = sum / 2; if (sum - min(cnt2, k) * 2 <= n - cnt2) puts("YES"); else puts("NO"); } } return 0; }
C
给一个数组$a[]$,每次可以从$i$跳到$i+a[i]$,停在$i$上可以获得$a_i$的价值,直到超过$n$,最大化价值。
从后往前递推。
#include <stdio.h> typedef long long ll; #define N 200005 int T, n; ll a[N], f[N]; ll max(ll x, ll y) { return x > y ? x : y; } int main() { #ifndef ONLINE_JUDGE freopen("sample.in", "r", stdin); #endif for (scanf("%d", &T); T--; ) { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); ll ans = 0; for (int i = n; i >= 1; i--) { if (i + a[i] > n) f[i] = a[i]; else f[i] = f[i + a[i]] + a[i]; ans = max(ans, f[i]); } printf("%lld\n", ans); } return 0; }
D
alice和bob玩游戏,给了一个长度为$n$的数组,每次可以选择移除一个元素,alice先手。若alice移除偶数,则alice得到价值为这个偶数的分数,若bob移除奇数则bob得到价值为这个奇数的分数,数组空的时候比两个人的得分谁高。如果两个人都足够聪明,判断胜负。
alice要移除一个偶数,一定是移除最大的偶数;若她要移除一个奇数,也一定是当前最大的奇数。进一步,发现不论是alice还是bob都一定会移除当前最大的数,如果当前分差(alice - bob)为$x$,最大的奇数为$y$,最大的偶数为$z$,假设alice拿走$z$,则分差就可以变为$x+z-y$,当$y > z$时不优,这时alice拿走$y$,可以使损失最小。
脑抽了,写了个分类讨论。
#include <stdio.h> typedef long long ll; #define N 200005 int T, n; ll a[N], b[N], c[N], tmp[N]; void sort(ll *arr, int l, int r) { if (l > r) return; if (l == r) return; int mid = (l + r) >> 1; sort(arr, l, mid), sort(arr, mid + 1, r); for (int i = l; i <= r; i++) tmp[i] = arr[i]; for (int p = l, p1 = l, p2 = mid + 1; p1 <= mid || p2 <= r; ++p) { if (p1 > mid) arr[p] = tmp[p2], ++p2; else if (p2 > r) arr[p] = tmp[p1], ++p1; else { if (tmp[p1] < tmp[p2]) arr[p] = tmp[p1], ++p1; else arr[p] = tmp[p2], ++p2; } } } int main() { #ifndef ONLINE_JUDGE freopen("sample.in", "r", stdin); #endif for (scanf("%d", &T); T--; ) { scanf("%d", &n); int cnt1 = 0, cnt2 = 0; for (int i = 1; i <= n; i++) { scanf("%lld", &a[i]); if (a[i] & 1) c[++cnt2] = a[i]; else b[++cnt1] = a[i]; } sort(b, 1, cnt1); sort(c, 1, cnt2); ll alice = 0, bob = 0; for (int i = 1, p1 = cnt1, p2 = cnt2; i <= n; i++) { if (i & 1) { if (!p1) --p2; else if (!p2) alice += b[p1], --p1; else { if (b[p1] > c[p2]) alice += b[p1], --p1; else --p2; } } else { if (!p2) --p1; else if (!p1) bob += c[p2], --p2; else { if (c[p2] > b[p1]) bob += c[p2], --p2; else --p1; } } } if (alice > bob) puts("Alice"); else if (alice < bob) puts("Bob"); else puts("Tie"); } return 0; }
E
给了$n$对二元组$(w, h)$,定义$j$在$i$前面为$(w_j < w_i & h_j < h_i) | (w_j < h_i & h_j < w_i)$,求每一个元素前面的任意一个元素编号,若没有,输出$-1$。
首先通过交换可以使$h_i \leq w_i$,那么元素$i$在元素$j$前面的充要条件变成$h_j < h_i & w_j < w_i$,二维偏序。
注意某个量相同的情况。
#include <stdio.h> typedef long long ll; #define N 200005 int T, n, ans[N]; struct Node { int w, h, id; } a[N], tmp[N]; void sort(int l, int r) { if (l == r) return; int mid = (l + r) >> 1; sort(l, mid), sort(mid + 1, r); for (int i = l; i <= r; i++) tmp[i] = a[i]; for (int p = l, p1 = l, p2 = mid + 1; p1 <= mid || p2 <= r; ++p) { if (p1 > mid) a[p] = tmp[p2], ++p2; else if (p2 > r) a[p] = tmp[p1], ++p1; else { if (tmp[p1].h < tmp[p2].h) a[p] = tmp[p1], ++p1; else a[p] = tmp[p2], ++p2; } } } int main() { #ifndef ONLINE_JUDGE freopen("sample.in", "r", stdin); #endif for (scanf("%d", &T); T--; ) { scanf("%d", &n); // printf("%d\n", n); for (int i = 1; i <= n; i++) { scanf("%d%d", &a[i].h, &a[i].w); if (a[i].h > a[i].w) { int inttmp = a[i].h; a[i].h = a[i].w; a[i].w = inttmp; } a[i].id = i; ans[i] = -1; } // for (int i = 1; i <= n; i++) // printf("%d %d %d\n", a[i].h, a[i].w, a[i].id); sort(1, n); // for (int i = 1; i <= n; i++) // printf("%d %d %d\n", a[i].h, a[i].w, a[i].id); a[0].h = a[1].h; for (int now = 0, p = 1, i = 1; i <= n; i++) { if (a[i].h != a[i - 1].h) { for (; p < i; p++) if (a[p].w < a[now].w || now == 0) now = p; } if (now != 0 && a[now].w < a[i].w) ans[a[i].id] = a[now].id; } for (int i = 1; i <= n; i++) printf("%d%c", ans[i], " \n"[i == n]); } return 0; }
F
先咕着
G
给一张有向图,设以$1$为源点的单源最短路为$d[]$,可以顺着$d$变大的道路走无数次,但是只能顺着$\leq d_i$的道路走最多一次,问从每一个点出发能走到的离$1$的最近距离。
分层图,一个点$x$拆成$x_0$和$x_1$表示走到$x$有/没有使用过$\leq d_i$的机会,发现这样子的图一定是一个DAG,记搜即可。
反证法:上下两层一样,若上下两层中有环,绕着环走一圈相当于$d_x > d_x$,矛盾,然后在两层之间走的时候只能上不能下,所以整张图没有环。
不想用C。
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef double db; typedef pair <int, int> pin; const int N = 2e5 + 5; const int inf = 0x3f3f3f3f; const ll P = 998244353LL; int T, n, m, tot, head[N << 1], dis[N], ans[N], f[N]; bool vis[N << 1]; struct Pathway { int x, y; } pat[N]; struct Edge { int to, nxt; } e[N << 1]; inline void add(int from, int to) { e[++tot].to = to; e[tot].nxt = head[from]; head[from] = tot; } template <typename T> inline void read(T &X) { char ch = 0; T op = 1; for (X = 0; ch > '9' || ch < '0'; ch = getchar()) if (ch == '-') op = -1; for (; ch >= '0' && ch <= '9'; ch = getchar()) X = (X * 10) + ch - '0'; X *= op; } priority_queue <pin> q; void dij(int s) { q.push(pin(dis[s] = 0, s)); for (; !q.empty(); ) { int x = q.top().second; q.pop(); if (vis[x]) continue; vis[x] = 1; for (int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; if (dis[y] > dis[x] + 1) { dis[y] = dis[x] + 1; q.push(pin(-dis[y], y)); } } } } int solve(int x) { if (x == 1) return f[x] = 0; if (f[x] != inf) return f[x]; int res = (x <= n ? dis[x] : dis[x - n]); for (int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; res = min(res, solve(y)); } return f[x] = res; } int main() { #ifndef ONLINE_JUDGE freopen("sample.in", "r", stdin); #endif for (read(T); T--; ) { read(n), read(m); tot = 0; for (int i = 1; i <= n; i++) dis[i] = inf, vis[i] = 0, head[i] = 0; for (int x, y, i = 1; i <= m; i++) { read(x), read(y); add(x, y); pat[i].x = x, pat[i].y = y; } dij(1); // for (int i = 1; i <= n; i++) printf("%d%c", dis[i], " \n"[i == n]); tot = 0; for (int i = 1; i <= n + n; i++) head[i] = 0, vis[i] = 0, f[i] = inf; for (int i = 1; i <= m; i++) { int x = pat[i].x, y = pat[i].y; if (dis[x] < dis[y]) add(x, y), add(x + n, y + n); else add(x, y + n); } for (int i = 1; i <= n; i++) printf("%d%c", solve(i), " \n"[i == n]); } return 0; }
标签:p2,693,p1,int,ll,CF,else,tmp,div3 来源: https://www.cnblogs.com/CzxingcHen/p/14258920.html