P8026 ONTAK2015 Bajtocja
题目只考察连通性,不考察图更具体的结构,所以可以用
两个点
因此,两个点
所以考虑对每个点
于是
我们动态地维护这
因为桶的下标是字符串哈希值域量级,桶用 unordered_map(如果会哈希表用哈希表也行)。
现在考虑动态维护
对于一次在第
所以不路径压缩,考虑按并查集树的大小启发式合并。这样以来,一个点在第
时间复杂度
另外这里所有字符串长度都是
typedef unsigned long long ull;
const int D = 205;
const int N = (int)5e3 + 5;
int rt[D][N];
std :: vector <int> t[D][N]; // t[k][u] 表示第 k 层图中以 u 为根的并查集树
ull ha[N], val[D];
int ans;
std :: unordered_map <ull, int> cnt;
inline void add(ull ha) {
int x = cnt[ha];
ans += 2 * x + 1;
++cnt[ha];
}
inline void del(ull ha) {
int x = cnt[ha];
ans -= 2 * x - 1;
if (--cnt[ha] == 0)
cnt.erase(ha); // 本题一个哈希值消失就很难再现,直接 erase 掉能显著减小常数。不 erase 也没什么问题。
}
int main() {
int d = read(), n = read(), m = read();
std :: mt19937_64 rng(std :: random_device{}());
for (int i = 1; i <= d; ++i)
val[i] = rng();
for (int i = 1; i <= d; ++i) {
for (int u = 1; u <= n; ++u) {
rt[i][u] = u;
ha[u] += u * val[i];
t[i][u].push_back(u);
}
}
for (int u = 1; u <= n; ++u)
add(ha[u]);
while (m--) {
int u = read(), v = read(), k = read();
u = rt[k][u]; v = rt[k][v];
if (u == v) {
printf("%d\n", ans);
continue;
}
if (t[k][v].size() > t[k][u].size())
std :: swap(u, v);
for (int x : t[k][v]) {
t[k][u].push_back(x);
rt[k][x] = u;
del(ha[x]);
ha[x] += (u - v) * val[k];
add(ha[x]);
}
t[k][v].clear();
printf("%d\n", ans);
}
return 0;
}
如果您是从洛谷题解过来的,觉得我的题解写的不错,解决了您的疑惑的话,请回到洛谷题解区给我题解点个赞,谢谢!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2020-07-18 [luogu p2234] [HNOI2002]营业额统计