[USACO13OPEN] Photo G 题解
前言
题目链接:洛谷。
题意简述
一个长度为
题目分析
方法 :差分约束
区间问题使用前缀和,退化成关于两端点的限制:
我们求
无解情况等价于存在负环,最短路不存在。
但是显然会超时,如何优化?SPFA 经典优化:SLF 优化。嗯,还差一个点,循环次数超过魔法数字
方法 :动态规划
差分约束显然不是正解。序列问题,决策是当前点是否染色,可以使用 DP 解决。
我们设
时间复杂度什么的先不谈,考虑怎么判断一个
有一个 trick:「恰好」等价于「不少于并且不大于」。
对于本题,恰好区间染色了一个位置,拆成两个限制,即至少染色一个位置,至多染色一个位置。
先考虑前者。由于
再考虑后者。如果一个区间同时包括了
预处理扫一扫是简单的。
转移方程变成:
由于
注意到我们不能直接取
时间复杂度:
Update on 2024.11.2:寻找到
经过打表发现
展开详细证明:
使用第二数学归纳法。假设所有
有
代码
方法 :差分约束
#include <cstdio> #include <iostream> #include <queue> #include <cstring> using namespace std; const int N = 200010, M = 100010; struct Graph { struct node { int to, len, nxt; } edge[N * 2 + M * 2]; int tot = 1, head[N]; void add(int u, int v, int w) { edge[++tot] = {v, w, head[u]}; head[u] = tot; } inline node & operator [] (const int x) { return edge[x]; } } xym; void smller(int u, int v, int w) { xym.add(v, u, w); } void bigger(int u, int v, int w) { smller(v, u, -w); } void equals(int u, int v, int w) { bigger(u, v, w); smller(u, v, w); } int n, m; int dis[N], cnt[N]; bool inq[N]; bool SPFA() { int yzh_i_love_you = 0; memset(dis, 0x3f, sizeof dis); deque<int> Q; Q.push_front(0), dis[0] = 0, cnt[0] = 1; inq[0] = true; while (!Q.empty()) { int now = Q.front(); Q.pop_front(); inq[now] = false; for (int i = xym.head[now]; i; i = xym[i].nxt) { int to = xym[i].to, w = xym[i].len; if (dis[to] > dis[now] + w) { dis[to] = dis[now] + w; cnt[to] = cnt[now] + 1; if (cnt[to] > n + 1 || ++yzh_i_love_you > 1736520) return false; if (!inq[to]) { inq[to] = true; if (!Q.empty() && dis[to] < dis[Q.front()]) Q.push_front(to); else Q.push_back(to); } } } } return true; } signed main() { #ifndef XuYueming freopen("photo.in", "r", stdin); freopen("photo.out", "w", stdout); #endif scanf("%d%d", &n, &m); for (int i = 1, l, r; i <= m; ++i) { scanf("%d%d", &l, &r); equals(r, l - 1, 1); } for (int i = 1; i <= n; ++i) { bigger(i, i - 1, 0); smller(i, i - 1, 1); } if (!SPFA()) return puts("-1"), 0; printf("%d", dis[n]); return 0; }
方法 :动态规划
单调队列
#include <cstdio> #include <iostream> using namespace std; const int N = 200010; int n, m, mx[N], mi[N]; int Q[N], head, tail = -1; int f[N]; signed main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n + 1; ++i) mx[i] = i; for (int i = 1, l, r; i <= m; i++) { scanf("%d%d", &l, &r); mx[r] = min(mx[r], l); mi[r + 1] = max(mi[r + 1], l); } for (int i = n; i >= 1; --i) mx[i] = min(mx[i], mx[i + 1]); for (int i = 2; i <= n + 1; ++i) mi[i] = max(mi[i], mi[i - 1]); for (int i = 1, j = 0; i <= n + 1; ++i) { while (j < mx[i]) { if (f[j] != -1) { while (head <= tail && f[Q[tail]] <= f[j]) --tail; Q[++tail] = j; } ++j; } while (head <= tail && Q[head] < mi[i]) ++head; if (head <= tail) f[i] = f[Q[head]] + 1; else f[i] = -1; } if (f[n + 1] == -1) puts("-1"); else printf("%d\n", f[n + 1] - 1); return 0; }
双指针
#include <cstdio> const int MAX = 1 << 23, N = 200001; int n, m, l, r, mx[N], mi[N], f[N]; char buf[MAX], *p(buf), *e(buf + MAX); #define getchar() (p == e && fread(p = buf, 1, MAX, stdin), *p++) [[always_inline]] inline void read(int &x) { x = 0; char ch = getchar(); for (; ch < 48; ch = getchar()); for (; 48 <= ch; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48); } [[always_inline]] inline void tomin(int& a, int& b) { b < a && (a = b); } [[always_inline]] inline void tomax(int& a, int& b) { b > a && (a = b); } main() { fread(buf, 1, MAX, stdin), read(n), read(m); for (register int i(1); i <= n + 1; ++i) mx[i] = i; for (; m--; ) read(l), read(r), tomin(mx[r], l), tomax(mi[r + 1], l); for (register int i(n); i; --i) tomin(mx[i], mx[i + 1]); for (register int i(1), j(0), k(0); i <= n + 1; ++i, tomax(mi[i], mi[i - 1])) { for (; j + 1 < mx[i]; ~f[++j] && (k = j)); f[i] = k >= mi[i] ? f[k] + 1 : -1; } ~f[n + 1] ? printf("%d", f[n + 1] - 1) : puts("-1"); }
本文作者:XuYueming,转载请注明原文链接:https://www.cnblogs.com/XuYueming/p/18397834。
若未作特殊说明,本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】