P8026 [ONTAK2015] Bajtocja 做题笔记

题目链接

一道好题,本来是做几道启发式合并玩玩,没想到是个哈希。

这一道题需要维护连通性,显然想到使用并查集。

如果两个点在某个图内的父亲相同,显然这两个点就连通了。

但是如果每链接一对点我们就遍历所有点对然后判断父亲,显然爆炸。

于是考虑借鉴一下 CSP 2022 T3 的思路,对于每个点处理一个值 weight

我们再对每张图中的每个点搞一个随机值 w,如果 i 的祖先是 j,那么给 weighti 加上 wj 即可。

这样我们就把每个点的 weight 设成了它在所有的图中祖先节点的权值之和,然后维护有多少对 weight 相等就行了。

这样错误的可能性很小,因为你很难构造出随机的方程,使得 a1+a2+a3++ad=b1+b2+b3+bd,并且还有一大堆连通性的要求。

但我第一发的模数是 998244353,WA 掉一个点,所以模数尽量开大点。

复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 300005, mod = 998244353;
#define For(i, a, b) for (int i = (a); i <= (b); ++ i)
inline void r (int &x) {
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') w = -1;
        ch = getchar ();
    }
    while (ch >= '0' && ch <= '9') {
        s = s * 10 + ch - 48;
        ch = getchar ();
    }
    x = s * w;
}
int d, n, m;
int w[201][5001], fa[201][5001], sz[201][5001];
int weight[5001];
unordered_map <int, int> b;
vector <int> v[201][5001];
int find (int k, int x) {
    if (fa[k][x] != x) {
        fa[k][x] = find (k, fa[k][x]);
        return fa[k][x];
    } else return x;
}
signed main () {
    srand (time (0) );
    r (d); r (n); r (m);
    For (i, 1, d) {
        For (j ,1, n) {
            w[i][j] = (long long) rand () * (long long) rand () % 129319283324;
            weight[j] += w[i][j];
            v[i][j].push_back (j);
            fa[i][j] = j;
            sz[i][j] = 1;
        }
    }
    For (i, 1, n) b[weight[i] ] ++;
    int ans = n;
    For (i, 1, m) {
        int x, y, k;
        r (x); r (y); r (k);
        int fx = find (k, x), fy = find (k, y);
        if (fx == fy) {
            cout << ans << "\n";
            continue;
        }
        if (sz[k][fx] > sz[k][fy]) swap (fx, fy);
        fa[k][fx] = fy;
        sz[k][fy] += sz[k][fx];
        for (int i : v[k][fx]) {
            ans -= (-- b[weight[i] ]) * 2;
            weight[i] -= w[k][fx];
            weight[i] += w[k][fy];
            ans += b[weight[i] ] * 2;
            b[weight[i] ] ++;
            v[k][fy].push_back (i);
        }
        v[k][fx].clear ();
        cout << ans << "\n";
    }
    return 0;
}
复制代码

 

posted @   Xy_top  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示