POI2007 完结撒花!
旅游景点atr
很简单的一道 dp 题,不说了。有意思的是官网上的标程把空间复杂度压成了 \( 2^k \),而我不知道这是怎么搞的,所以官网上提交会 \( MLE \)
办公楼biu
很容易想到求补图的联通块,然后随便敲了个 \( BFS \),果断 \( WA \)
考虑用并查集把相同联通块的点圈起来,类似缩点的思想,这样一边枚举点一边减少点,可以卡着过

#include <bits/stdc++.h> using namespace std; const int N = 1e5+5; const int M = 2e6+5; vector<int> g[N]; int n, m, a, b; int col[N], cnt[N]; int fa[N]; int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } int main() { scanf("%d %d", &n, &m); for (int _ = 1; _ <= m; _++) { scanf("%d %d", &a, &b); g[a].push_back(b); g[b].push_back(a); } for (int i = 1; i <= n+1; i++) { fa[i] = i; } int ans = 0; for (int i = 1; i <= n; i = find(i+1)) { queue<int> q; q.push(i); cnt[++ans] = 1; while (!q.empty()) { int u = q.front(); q.pop(); fa[u] = find(u+1); for (int i = 0; i < g[u].size(); i++) { col[g[u][i]] = u; } for (int i = find(1); i <= n; i = find(i+1)) { if (col[i] != u) { fa[i] = find(i+1); cnt[ans]++; q.push(i); } } } } printf("%d\n", ans); sort(cnt+1, cnt+1+ans); for (int i = 1; i <= ans; i++) { printf("%d ", cnt[i]); } return 0; }
树Drz
这题据说要用 9 个线段树,所以我没做。。。
对称轴osi
啊。。。这题初看不可捉的样子,然而千古神犇 vfk 说对称轴平分 360 角,利用这个结论就好捉了
当然类似无序运动那题搞个字符串也可以的(然而这两种方法都没有实现出来,太懒啦QWQ)
Zap
(好奇为什么没有中文)
(就叫它密码好了)
这题用到了神仙莫比乌斯函数的性质哦 QWQ
还顺带用到了分块
式子懒得敲咯,网上一大堆
代码留着吧,有点小技巧在里面的

#include <bits/stdc++.h> using namespace std; const int N = 5e4+1; int prime[N]; int mu[N], sum[N]; int t, n, m, d, ct; bool not_prime[N]; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); mu[1] = 1; for (int i = 2; i < N; i++) { if (!not_prime[i]) { prime[++ct] = i; mu[i] = -1; } for (int j = 1; j <= ct && i * prime[j] < N; j++) { not_prime[i * prime[j]] = true; if (i % prime[j] == 0) { mu[i * prime[j]] = 0; break; } mu[i * prime[j]] = -mu[i]; } } for (int i = 1; i < N; i++) { sum[i] = sum[i-1] + mu[i]; } cin >> t; while (t--) { cin >> n >> m >> d; if (n > m) { swap(n, m); } n /= d, m /= d; int ans = 0; for (int i = 1, j = 1; i <= n; i = j + 1) { j = min(n / (n / i), m / (m / i)); ans += (sum[j] - sum[i-1]) * (n / i) * (m / i); } cout << ans << endl; } return 0; }
可惜不知道为什么 \( TLE \) 了一个点 QWQ
山峰和山谷Grz
试机水题
大都市meg
据说可用 dfs + 树状数组水过
洪水pow
据说可用 dfs + 并查集水过
石头花园SKA
好神奇的推论题哦
从没想过要把石头放在同一边
而且也没想过要分四种情况
立方体大作战tet
贪心搞一搞咯
驾驶考试egz
呀,想歪了一点点
大概就是求两个 dp 数组然后滑动窗口搞一搞的咯
网上题解漫天飞
只留个还算美观的代码吧

#include <bits/stdc++.h> using namespace std; const int N = 1e5+5; int c[N]; int n, m, p, k, x, h, d; vector<int> pth[2][N], lis[2][N]; int bit[N], lf[N], rf[N]; int lowbit(int x) { return x & -x; } int ask(int p) { int ret = 0; for (; p > 0; p -= lowbit(p)) { ret = max(ret, bit[p]); } return ret; } void change(int p, int v) { for (; p <= m; p += lowbit(p)) { bit[p] = max(bit[p], v); } } void run(int s, int d, int t, int *f) { int ls = 0; memset(bit, 0, sizeof(int)*(m+1)); for (int i = s, j = 2; j <= n; j++, i += d) { for (int k = 0; k < pth[t][i].size(); k++) { int ak = ask(pth[t][i][k])+1; ls = max(ls, ak); lis[t][i].push_back(ak); } for (int k = 0; k < lis[t][i].size(); k++) { change(pth[t][i][k], lis[t][i][k]); } f[i] = !t ? i - 1 - ls : n - i - ls; } } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m >> p >> k; m++; for (int i = 1; i <= p; i++) { cin >> x >> h >> d; pth[d^1][x+d].push_back(m-h); } run(2, 1, 0, lf); run(n-1, -1, 1, rf); int ans = 0, buf = 0; for (int i = 1, j = 1; i <= n; i++) { while (j <= n && lf[j] + rf[i] <= k) { j++; } ans = max(ans, j - i); if (!lf[i] && !rf[i]) { buf++; } } cout << ans - buf << endl; return 0; }
天然气管道Gaz
呃。。。实在佩服 POI 的题目
水题硬生生想破脑袋
堆积木Klo
哇。。。听说这类问题有个很 NB 的名字叫二维偏序的。。。
当然还有大名鼎鼎的三维偏序。。。
dp 式子省略咯(反正网上满篇飞)
砝码Odw
orz 又是贪心,而且貌似很显然的样子
搞搞进位制就好了
四进制的天平Wag
呀,这个 dp 有意思哦
首先有几个贪心的推论要了解的
然后就可以大胆的 dp 啦(没错我还是抄的别人的代码)(所以不敢贴出来)
可怜的我只会推结论不会写 dp
而且结论貌似也很显然。。。
小结
每道不可捉的题背后都有一个可捉的推论。