[Hackerrank University Codesprint 5] Interesting Trip (拓扑dp+可持久化线段树维护哈希+二分加速比较字典序)
[Hackerrank University Codesprint 5] Interesting Trip
拓扑dp+可持久化线段树维护哈希+二分加速比较字典序
因为是有向无环图,所以考虑拓扑排序上 dp。当前
那么设
考虑字典序的比较,朴素需要
现在需要时刻维护
关于拓扑排序的实现,普通的做法是队列,但是这样转移时发送式的,而我们需要比较所有的
复杂度
#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define fi first
#define se second
#define pb push_back
using i64 = long long;
using ull = unsigned long long;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 10, p = 20242024, mod = 1234567891;
int n, m, idx, s, tt;
int a[N], f[N];
std::vector<int> e[N];
i64 pw[N];
struct SEG {
int l, r, len;
i64 v;
} t[N * 20];
void pushup(int u) {
t[u].v = (t[t[u].l].v * pw[t[t[u].r].len] % mod + t[t[u].r].v) % mod;
t[u].len = t[t[u].l].len + t[t[u].r].len;
}
void ins(int &o, int u, int l, int r, int x, int y) {
o = ++idx;
t[o] = t[u];
if(l == r) {
t[o] = {l, r, 1, y};
return;
}
int mid = (l + r) >> 1;
if(x <= mid) ins(t[o].l, t[u].l, l, mid, x, y);
else ins(t[o].r, t[u].r, mid + 1, r, x, y);
pushup(o);
}
SEG qry(int u, int l, int r, int L, int R) {
if(L <= l && r <= R) return t[u];
int mid = (l + r) >> 1;
if(R <= mid) return qry(t[u].l, l, mid, L, R);
if(L > mid) return qry(t[u].r, mid + 1, r, L, R);
SEG ret = {0, 0, 0, 0}, ls = qry(t[u].l, l, mid, L, R), rs = qry(t[u].r, mid + 1, r, L, R);
ret.v = (ls.v * pw[rs.len] % mod + rs.v) % mod, ret.len = ls.len + rs.len;
return ret;
}
bool compare(int u, int v) {
if(!f[u]) return 1; //直接覆盖
else if(!f[v]) return 0; // v 无用
int l = 1, r = std::min(t[f[u]].len, t[f[v]].len), ret = 0;
while(l <= r) {
int mid = (l + r) >> 1;
if(qry(f[u], 1, n, n - t[f[u]].len + 1, n - t[f[u]].len + mid).v != qry(f[v], 1, n, n - t[f[v]].len + 1, n - t[f[v]].len + mid).v) r = mid - 1;
else l = mid + 1, ret = mid;
}
if(ret == std::min(t[f[u]].len, t[f[v]].len)) {
if(t[f[u]].len == ret) return 0;
else return 1;
} //特判 s in t | t in s 的情况
return qry(f[u], 1, n, n - t[f[u]].len + ret + 1, n - t[f[u]].len + ret + 1).v > qry(f[v], 1, n, n - t[f[v]].len + ret + 1, n - t[f[v]].len + ret + 1).v;
}
void print(int u) {
if(t[u].l == t[u].r) {
std::cout << (char)(t[u].v + 'a');
return;
}
if(t[u].l) print(t[u].l);
if(t[u].r) print(t[u].r);
}
int vis[N];
void dfs(int u) {
vis[u] = 1;
int mn = 0;
for(auto v : e[u]) {
if(!vis[v]) dfs(v);
if(compare(mn, v)) mn = v;
}
if(f[mn]) ins(f[u], f[mn], 1, n, n - t[f[mn]].len, a[u]);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n >> m;
std::string S;
std::cin >> S;
S = "#" + S;
for(int i = 1; i <= n; i++) a[i] = S[i] - 'a';
pw[0] = 1;
for(int i = 1; i <= n; i++) pw[i] = pw[i - 1] * p % mod;
for(int i = 1; i <= m; i++) {
int u, v;
std::cin >> u >> v;
e[u].pb(v);
}
std::cin >> s >> tt;
ins(f[tt], 0, 1, n, n, a[tt]);
dfs(s);
if(!f[s]) std::cout << "No way\n";
else {
print(f[s]);
}
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析