首页 > 其他分享 >abc372E K-th Largest Connected Components

abc372E K-th Largest Connected Components

时间:2024-10-07 17:33:41浏览次数:1  
标签:node int abc372E son Connected Components ans else data

有N个顶点的无向图,最初没有边,接下来有Q组询问,格式如下:

  • 1 u v:在顶点u和v之间加一条边;
  • 2 x k: 问与顶点v连通的分量中,顶点编号第k大的是谁?如果不存在,输出-1.
    1<=N,Q<=2E5,1<=u<v<=N, 1<=x<=N, 1<=k<=10

分析:由于k比较小,直接用vector维护连通分量的顶点集合,在合并时,如果顶点数超过k,则只取最大的k个。剩下的就是并查集模板操作。

#include <bits/stdc++.h>
using i64 = long long;

struct Dsu {
    void init(int n) {
        fa.resize(n + 1);
        has.resize(n + 1);
        for (int i = 1; i <= n; i++) {
            fa[i] = i;
            has[i].push_back(i);
        }
    }
    int leader(int x) {
        return x == fa[x] ? x : fa[x] = leader(fa[x]);
    }
    void join(int x, int y) {
        x = leader(x);
        y = leader(y);
        if (x != y) {
            if (has[x].size() < has[y].size()) {
                std::swap(x, y);
            }
            for (auto i : has[y]) {
                has[x].push_back(i);
            }
            std::sort(has[x].rbegin(), has[x].rend());
            if (has[x].size() > 10) {
                has[x].resize(10);
            }
            fa[y] = x;
        }
    }
    std::vector<int> fa;
    std::vector<std::vector<int>> has;
};

void solve() {
    int N, Q;
    std::cin >> N >> Q;
    Dsu dsu;
    dsu.init(N);
    for (int i = 1; i <= Q; i++) {
        int x, y, z;
        std::cin >> x >> y >> z;
        if (x == 1) {
            dsu.join(y, z);
        } else {
            int u = dsu.leader(y);
            if (z <= dsu.has[u].size()) {
                std::cout << dsu.has[u][z - 1] << "\n";
            } else {
                std::cout << "-1\n";
            }
        }
    }
}

int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

如果k的范围是[1,N],可以考虑用平衡树来维护连通分量,需要用到启发式合并。

#include <bits/stdc++.h>
using i64 = long long;

template <typename TYPE>
struct Treap {
    struct Node {
        TYPE data;
        int rnd, siz, dup, son[2];
        Node() { memset(&data, 0, sizeof(data)); rnd = siz = son[0] = son[1] = 0; }
        Node(const TYPE &d, int cnt=1) { init(d, cnt); }
        void init(const TYPE & d, int cnt) { data = d; dup = cnt; rnd = rand(); siz = 1; son[0] = son[1] = 0; }
    };
    Treap(int multi=1):multiple(multi) { reset(); }
    void setmulti(int multi) { multiple = multi; }
    int newnode(const TYPE & d, int cnt) {
        if (!reuse.empty()) {
            int r = reuse.front();
            reuse.pop_front();
            node[r].init(d, cnt);
            return r;
        }
        node.push_back({d, cnt});
        return node.size() - 1;
    }
    void reset() { root = 0; node.resize(1); reuse.clear(); }
    void maintain(int x) {
        node[x].siz = node[x].dup;
        if (node[x].son[0]) {
            node[x].siz += node[node[x].son[0]].siz;
        }
        if (node[x].son[1]) {
            node[x].siz += node[node[x].son[1]].siz;
        }
    }
    void rotate(int d, int &r) {
        int k = node[r].son[d^1];
        node[r].son[d^1] = node[k].son[d];
        node[k].son[d] = r;
        maintain(r);
        maintain(k);
        r = k;
    }
    void insert(const TYPE &data, int cnt, int &r) {
        if (r) {
            if (!(data < node[r].data) && !(node[r].data < data)) {
                if (multiple) {
                    node[r].dup += cnt;
                    maintain(r);
                }
            } else {
                int d = data < node[r].data ? 0 : 1;
                // avoid push_back -> realloc
                int u = node[r].son[d];
                insert(data, cnt, u);
                node[r].son[d] = u;
                if (node[node[r].son[d]].rnd > node[r].rnd) {
                    rotate(d^1, r);
                } else {
                    maintain(r);
                }
            }
        } else {
            r = newnode(data, cnt);
        }
    }
    TYPE kth(int k) {
        assert(1 <= k && k <= size());
        for (int r = root; r; ) {
            int x = node[r].son[0] ? node[node[r].son[0]].siz : 0;
            int y = node[r].dup;
            if (k <= x) {
                r = node[r].son[0];
            } else if (k <= x + y) {
                return node[r].data;
            } else {
                k -= x + y;
                r = node[r].son[1];
            }
        }
        assert(k == 0);
        return 0;
    }
    TYPE Kth(int k) {
        assert(1 <= k && k <= size());
        for (int r = root; r; ) {
            int x = node[r].son[1] ? node[node[r].son[1]].siz : 0;
            int y = node[r].dup;
            if (k <= x) {
                r = node[r].son[1];
            } else if (k <= x + y) {
                return node[r].data;
            } else {
                k -= x + y;
                r = node[r].son[0];
            }
        }
        assert(k == 0);
        return 0;
    }
    void erase(const TYPE& data, int cnt, int & r) {
        if (r == 0) return;
        int d = -1;
        if (data < node[r].data) {
            d = 0;
        } else if (node[r].data < data) {
            d = 1;
        }
        if (d == -1) {
            node[r].dup -= cnt;
            if (node[r].dup > 0) {
                maintain(r);
            } else {
                if (node[r].son[0] == 0) {
                    reuse.push_back(r);
                    r = node[r].son[1];
                } else if (node[r].son[1] == 0) {
                    reuse.push_back(r);
                    r = node[r].son[0];
                } else {
                    int dd = node[node[r].son[0]].rnd > node[node[r].son[1]].rnd ? 1 : 0;
                    rotate(dd, r);
                    erase(data, node[r].son[dd]);
                }
            }
        } else {
            erase(data, cnt, node[r].son[d]);
        }
        if (r) maintain(r);
    }
    int ltcnt(const TYPE &data) {
        int ans = 0;
        for (int r = root; r; ) {
            int x = node[r].son[0] ? node[node[r].son[0]].siz : 0;
            if (node[r].data < data) {
                ans += node[r].dup + x;
                r = node[r].son[1];
            } else if (data < node[r].data) {
                r = node[r].son[0];
            } else {
                ans += x;
                break;
            }
        }
        return ans;
    }
    int gtcnt(const TYPE &data) {
        int ans = 0;
        for (int r = root; r; ) {
            int x = node[r].son[1] ? node[node[r].son[1]].siz : 0;
            if (node[r].data < data) {
                r = node[r].son[1];
            } else if (data < node[r].data) {
                ans += node[r].dup + x;
                r = node[r].son[0];
            } else {
                ans += x;
                break;
            }
        }
        return ans;
    }
    int count(const TYPE &data) {
        for (int r = root; r; ) {
            if (data < node[r].data) {
                r = node[r].son[0];
            } else if (node[r].data < data) {
                r = node[r].son[1];
            } else {
                return node[r].dup;
            }
        }
        return 0;
    }
    std::pair<bool,TYPE> prev(const TYPE &data) {
        std::pair<bool,TYPE> ans = {false, 0};
        for (int r = root; r; ) {
            if (node[r].data < data) {
                if (ans.first) {
                    ans.second = std::max(ans.second, node[r].data);
                } else {
                    ans = {true, node[r].data};
                }
                r = node[r].son[1];
            } else {
                r = node[r].son[0];
            }
        }
        return ans;
    }       
    std::pair<bool,TYPE> next(const TYPE &data) {
        std::pair<bool,TYPE> ans = {false, 0};
        for (int r = root; r; ) {
            if (data < node[r].data) {
                if (ans.first) {
                    ans.second = std::min(ans.second, node[r].data);
                } else {
                    ans = {true, node[r].data};
                }
                r = node[r].son[0];
            } else {
                r = node[r].son[1];
            }
        }
        return ans;
    }
    void dofetch(int r, std::vector<std::pair<TYPE,int>> &vec) const {
        if (r) {
            dofetch(node[r].son[0], vec);
            vec.push_back({node[r].data, node[r].dup});
            dofetch(node[r].son[1], vec);
        }
    }
    void fetch(std::vector<std::pair<TYPE,int>> &vec) const {
        dofetch(root, vec);
    }
    void merge(const Treap<TYPE> &rhs) {
        std::vector<std::pair<TYPE,int>> vp;
        rhs.fetch(vp);
        for (auto &pr : vp) {
            insert(pr.first, pr.second);
        }
    }
    std::vector<Node> node;
    std::deque<int> reuse;
    int root, multiple;
    void insert(const TYPE& data, int cnt=1) { insert(data, cnt, root); }
    void erase(const TYPE& data, int cnt=1) { return erase(data, cnt, root); }
    int size() const { return root ? node[root].siz : 0; }
    int lecnt(const TYPE& data) { return size() - gtcnt(data, root); }
    int gecnt(const TYPE& data) { return size() - ltcnt(data, root); }
};

struct Dsu {
    void init(int n) {
        fa.resize(n + 1);
        has.resize(n + 1);
        for (int i = 1; i <= n; i++) {
            fa[i] = i;
            has[i].insert(i);
        }
    }
    int leader(int x) {
        return x == fa[x] ? x : fa[x] = leader(fa[x]);
    }
    void join(int x, int y) {
        x = leader(x);
        y = leader(y);
        if (x != y) {
            if (has[x].size() < has[y].size()) {
                std::swap(x, y);
            }
            has[x].merge(has[y]);
            fa[y] = x;
        }
    }
    std::vector<int> fa;
    std::vector<Treap<int>> has;
};

void solve() {
    int N, Q;
    std::cin >> N >> Q;
    Dsu dsu;
    dsu.init(N);
    for (int i = 1; i <= Q; i++) {
        int x, y, z;
        std::cin >> x >> y >> z;
        if (x == 1) {
            dsu.join(y, z);
        } else {
            int u = dsu.leader(y);
            if (z <= dsu.has[u].size()) {
                std::cout << dsu.has[u].Kth(z) << "\n";
            } else {
                std::cout << "-1\n";
            }
        }
    }
}

int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

标签:node,int,abc372E,son,Connected,Components,ans,else,data
From: https://www.cnblogs.com/chenfy27/p/18450355

相关文章

  • 题解:AT_abc372_e [ABC372E] K-th Largest Connected Components
    题意给出\(q\)个操作。将\(u\)和\(v\)连边。问\(u\)所在的连通块中编号第\(k\)大的点。思路连通块很容易想到并查集,求第\(k\)大可以用平衡树(虽然赛时没看到\(k\le10\)),合并时将信息从将小的连通块合并到大的连通块,这样可以减少时间复杂度。什么?你不会写平衡......
  • CF1270H Number of Components 题解
    Description给一个长度为\(n\)的数组\(a\),\(a\)中的元素两两不同。对于每个数对\((i,j)(i<j)\),若\(a_i<a_j\),则让\(i\)向\(j\)连一条边。求图中连通块个数。支持\(q\)次修改数组某个位置的值,每次修改后输出图中连通块个数。\(n,q\le5\times10^5,1\lea_i\le10^......
  • 题解:AT_abc372_e [ABC372E] K-th Largest Connected Components
    博客内食用更佳这道题的\(k\le10\)其实没什么用,代码区别仅在于手写平衡树和使用内置容器。这道题让查询与一个节点相连的所有点的信息,所以不难想到并查集。又因为让查询第\(k\)大,所以不难想到平衡树和线段树启发式合并。至此思路明显。我们对并查集中的每个节点开一个平......
  • winform DevComponents.DotNetBar2 添加到工具栏方法
    原文链接:https://blog.csdn.net/Pei_hua100/article/details/126284898当C#项目引入皮肤组件,或其他组件是,发现工具框里面没有引用的组件怎么办?1.组件的引用我是把下载好的*.dll组件,复制到项目的\bin\Debug\路径下,然后在项目处右键-->添加引用,这样组件就引入项目了可以使用了。......
  • 解决React Warning: Function components cannot be given refs. Attempts to access
    问题当我使用如下方式调用组件子组件UploadModal并且绑定Ref时React报错“Warning:Functioncomponentscannotbegivenrefs.Attemptstoaccessthisrefwillfail.DidyoumeantouseReact.forwardRef()?”;constUploadModalRef=useRef(null);constopenUploadModa......
  • STM32No target connected解决办法
    stm32使用stlink下载程序报错目标未连接解决办法之一一.产生原因二.解决办法一.产生原因使用stlink下载程序时遇到Notargetconnected报错,产生这个有很多原因,我这里的原因是由于这是我自己画的板子有问题。请看pcb我的下载电路直接接到了铺铜上,当仅使用stlink供......
  • 微信小程序报错:Component is not found in path "components/comp/comp.js"
    完整错误jsEnginScriptError:Componentisnotfoundinpath"components/comp/comp.js"(usingbypages/index/index);onAppRouteError:Componentisnotfoundinpath"components/comp/comp.js"(usingbypages/index/index) ine(...) ...错误......
  • 微信小程序报错:Component is not found in path "components/comp/comp.js"
    完整错误jsEnginScriptError:Componentisnotfoundinpath"components/comp/comp.js"(usingbypages/index/index);onAppRouteError:Componentisnotfoundinpath"components/comp/comp.js"(usingbypages/index/index) ine(...) ...错误......
  • ProComponents——ProForm,设置初始值后,点击【重置】按钮,值已清除但页面未更新
     我的问题umi+antd,使用ProComponents的QueryFilter表单进行列表筛选,首页有个进入列表的快捷跳转,会筛选列表状态(在线1/离线0)。设置筛选状态初始值为1后,点击【重置】按钮:1.打印初始值1已清除,但页面上未更新,仍显示筛选在线状态2.点击2次【重置】按钮,页面才会更新3.点击下拉框的......
  • OPenCV结构分析与形状描述符(5)查找图像中的连通组件的函数connectedComponents()的使用
    操作系统:ubuntu22.04OpenCV版本:OpenCV4.9IDE:VisualStudioCode编程语言:C++11算法描述connectedComponents函数计算布尔图像的连通组件标签图像。该函数接受一个具有4或8连通性的二值图像,并返回N,即标签总数(标签范围为[0,N-1],其中0代表背景标签)。ltype参数指......