D1T1 铺地毯
#include <cstdio> const int MAXN = 100001; int n, x, y, a[MAXN], b[MAXN], g[MAXN], k[MAXN]; int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d%d%d%d", &a[i], &b[i], &g[i], &k[i]); scanf("%d%d", &x, &y); int ans = 0; for (int i = 1; i <= n; i++) if (a[i] <= x && x <= a[i] + g[i] && b[i] <= y && y <= b[i] + k[i]) ans = i; printf("%d\n", ans); return 0; }
D1T2 选择客栈
#include<cstdio> using namespace std; int f[200001], sav[200001], ans[200001], num[200001]; int n, p, k, cnt = 0; int main() { scanf("%d%d%d", &n, &k, &p); for (int i = 1; i <= n; i++) { int color, cost; scanf("%d%d", &color, &cost); if (cost <= p) f[i] = f[i - 1] + 1; else f[i] = f[i - 1]; if (sav[color] == 0) { sav[color] = i; num[color]++; continue; } if (f[i] - f[sav[color] - 1] > 0) ans[i] = num[color]; else ans[i] = ans[sav[color]]; sav[color] = i; num[color]++; } for (int i = 1; i <= n; i++) cnt += ans[i]; printf("%d\n", cnt); return 0; }
D1T3 Mayan游戏
Mayan游戏写起来比较棘手,做法的话,就是上DFS。有两个剪枝操作:某种颜色存在但是个数小于3没法消除;如果一个方块左边也是方块就不必左移,因为右移效果一样字典序更小。
#include <cstdio> #include <cstdlib> #include <cstring> void swap(int &a, int &b) { int c = a; a = b; b = c; } int n; struct map { int a[5][7]; bool d[5][7]; void Read() { memset(a, 0, sizeof(a)); memset(d, 0, sizeof(d)); for (int i = 0; i < 5; i++) { int t1, t2 = 0; scanf("%d", &t1); while (t1) { a[i][t2++] = t1; scanf("%d", &t1); } } } void Falldown(int i) { int pop = 0; for (int j = 0; j < 7; j++) if (a[i][j]) { a[i][pop++] = a[i][j]; if (j >= pop) a[i][j] = 0; } } void Fall() { for (int i = 0; i < 5; i++) Falldown(i); } bool Combo() { memset(d, 0, sizeof(d)); bool ret = 0; for (int i = 0; i < 5; i++) for (int j = 0; j < 7; j++) { if (a[i][j] == 0) continue; if (0 < i && i < 4) if (a[i - 1][j] == a[i][j] && a[i][j] == a[i + 1][j]) { d[i - 1][j] = d[i][j] = d[i + 1][j] = 1; ret = 1; } if (0 < j && j < 6) if (a[i][j - 1] == a[i][j] && a[i][j] == a[i][j + 1]) { d[i][j - 1] = d[i][j] = d[i][j + 1] = 1; ret = 1; } } return ret; } void Collapse() { for (int i = 0; i < 5; i++) for (int j = 0; j < 7; j++) if (d[i][j]) a[i][j] = 0; memset(d, 0, sizeof(d)); } void Move(int i, int j, int k) { swap(a[i][j], a[i + k][j]); Falldown(i), Falldown(i + k); while (Combo()) { Collapse(); Fall(); } } bool Empty() { for (int i = 0; i < 5; i++) if (a[i][0]) return 0; return 1; } int GetMin() { int cnt[11] = {0}; for (int i = 0; i < 5; i++) for (int j = 0; j < 7; j++) if (a[i][j]) cnt[a[i][j]]++; int min = 35; for (int i = 1; i <= 10; i++) if (cnt[i] && cnt[i] < min) min = cnt[i]; return min; } } sta; struct Node { int a, b, c; void Load(int A, int B, int C) { a = A, b = B, c = C; } } ans[100]; void dfs(int t) { if (sta.Empty()) { for (int i = 1; i <= t; i++) printf("%d %d %d\n", ans[i].a, ans[i].b, ans[i].c); exit(0); } if (t == n) return; if (sta.GetMin() <= 2) return; map bak = sta; for (int i = 0; i < 5; i++) for (int j = 0; j < 7; j++) { if (sta.a[i][j] == 0) continue; if (i < 4 && sta.a[i][j] != sta.a[i + 1][j]) { ans[t + 1].Load(i, j, 1); sta.Move(i, j, 1); dfs(t + 1); sta = bak; } if (i > 0 && sta.a[i - 1][j] == 0) { ans[t + 1].Load(i, j, -1); sta.Move(i, j, -1); dfs(t + 1); sta = bak; } } } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); scanf("%d", &n); sta.Read(); dfs(0); printf("-1\n"); return 0; }
D2T1 计算系数
杨辉三角就可以了~
#include <cstdio> #include <algorithm> const int M = 10007; using namespace std; int f[1001][1001]; int a, b, k, n, m; int main() { long long ans = 1; scanf("%d%d%d%d%d", &a, &b, &k, &n, &m); f[1][1] = f[1][2] = 1; for (int i = 2; i <= k; i++) for (int j = 1; j <= i + 1; j++) f[i][j] = (f[i - 1][j - 1] + f[i - 1][j]) % M; ans = f[k][m + 1]; for (int i = 1; i <= n; i++) ans = (ans * a) % M; for (int j = 1; j <= m; j++) ans = (ans * b) % M; printf("%d", ans); return 0; }
D2T2 聪明的质检员
二分法计算就可以了。P.S.VIJOS是windows评测,我一开始%lld没过,然并卵
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> using namespace std; long long n, m, S, w[200001], v[200001], l[200001], r[200001], arr[200001]; long long sum1[200001], sum2[200001]; long long fun(int k) { long long ret = 0; for (int i = 1; i <= n; i++) { if (w[i] >= k) { sum1[i] = sum1[i - 1] + 1; sum2[i] = sum2[i - 1] + v[i]; } else { sum1[i] = sum1[i - 1]; sum2[i] = sum2[i - 1]; } } for (int i = 1; i <= m; i++) ret += (sum1[r[i]] - sum1[l[i] - 1]) * (sum2[r[i]] - sum2[l[i] - 1]); return S - ret; } long long find(int L, int R) { if (L == R) return abs(fun(L)); long long M = (L + R) / 2; long long tmp = fun(arr[M]); long long ret = abs(tmp); if (tmp > 0) ret = min(find(L, M), ret); else if (tmp < 0) ret = min(find(M + 1, R), ret); return ret; } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); scanf("%I64d%I64d%I64d", &n, &m, &S); for (int i = 1; i <= n; i++){ scanf("%I64d%I64d", &w[i], &v[i]); arr[i] = w[i]; } sort(arr + 1, arr + n + 1); for (int i = 1; i <= m; i++) scanf("%I64d%I64d", &l[i], &r[i]); long long ans = find(1, n); printf("%I64d", ans); return 0; }
D2T3 观光公交
易见每个旅客上车时间都已固定,答案取决于下车时间,所以得出贪心操作正确性。然后就是每次氮气都用在在车上人最多的时候。
#include <cstdio> int n, m, k, t, a, b; int d[1001], lim[1001], sce[1001], up[1001], down[1001]; int max(int a, int b) { return a > b ? a : b; } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); int p = 0; scanf("%d%d%d", &n, &m, &k); for (int i = 1; i < n; i++) scanf("%d", &d[i]); for (int i = 1; i <= m; i++) { scanf("%d%d%d", &t, &a, &b); up[a]++, down[b]++; sce[a] = max(sce[a], t); p += t; } for (int i = 1; i <= n; i++) lim[i] = max(lim[i - 1], sce[i - 1]) + d[i - 1]; while (k--) { int cnt = 0, _max = 0, t = 0; for (int i = n; i > 1; i--) { if (lim[i] <= sce[i]) cnt = 0; cnt += down[i]; if (d[i - 1] && cnt > _max) _max = cnt, t = i - 1; } if (!t) break; d[t]--; for (int i = t + 1; i <= n; i++) lim[i] = max(lim[i - 1], sce[i - 1]) + d[i - 1]; } int ans = 0; for (int i = 1; i <= n; i++) { lim[i] = max(lim[i - 1], sce[i - 1]) + d[i - 1]; ans += down[i] * lim[i]; } printf("%d\n", ans - p); return 0; }