ABC232G

直接连边是 O(N2) 的,考虑优化建图。构建 M 个虚点,分别是 ¯0,¯1,,¯M1。然后对于 k[0,M1],连边 ¯k¯(k+1)modM,边权为 1

对于 i[1,N],连边 i¯Ai+M,边权为 0。对于 i[1,N],连边 ¯Bii,边权为 0

借用一下官方题解的图:




但是时间复杂度依旧寄。考虑继续优化,可以发现,环上有用的虚点个数至多 2N 个,所以缩点,就可以了。

再借一下官方题解的图:

这样之后跑个 Dij 就好了。

Code:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
typedef pair <int, int> pii;
typedef long long ll;
const int N = 200005, M = 600005;
int n, m;
int a[N], b[N];
map <int, int> mp; int tot;
vector <pii> g[M];
ll dis[M]; bool vis[M];

void dij() {
	memset(dis, 0x3f, sizeof dis); dis[1] = 0;
	priority_queue <pii> q; q.push(pii(0, 1));
	while (!q.empty()) {
		int u = q.top().se; q.pop();
		if (vis[u]) continue;
		vis[u] = 1;
		for (auto e : g[u]) {
			int v = e.fi, w = e.se;
			if (dis[v] > dis[u] + w) {
				dis[v] = dis[u] + w;
				q.push(pii(-dis[v], v));
			}
		}
	}
}

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
	for (int i = 1; i <= n; ++i) scanf("%d", &b[i]);
	tot = n;
	for (int i = 1; i <= n; ++i) {
		if (!mp.count(b[i])) mp[b[i]] = ++tot;
		if (!mp.count(-a[i] + m)) mp[-a[i] + m] = ++tot;
		g[i].pb(pii(mp[-a[i] + m], 0));
		g[mp[b[i]]].pb(pii(i, 0));
	}
	for (auto cur : mp) {
		auto nxt = mp.upper_bound(cur.fi);
		if (nxt == mp.end()) nxt = mp.begin();
		auto tmp = *nxt;
		g[cur.se].pb(pii(tmp.se, (tmp.fi - cur.fi + m) % m));
	}
	dij();
	printf("%lld", dis[n]);
	return 0;
}
posted @   Kobe303  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示