博客
关于我
并查集+线段树合并:P3224-永无乡
阅读量:198 次
发布时间:2019-02-28

本文共 2561 字,大约阅读时间需要 8 分钟。

并查集与线段树结合解决集合中的第k大权值查询问题

问题描述

在处理一系列权值点的集合操作时,我们需要在合并两个集合时,能够快速查询其中的第k大权值。传统的并查集难以满足这一需求,而结合并查集与线段树的方法可以有效解决问题。

解决方案

我们采用并查集结构,每个集合对应一个线段树。这样,在合并两个集合时,可以直接将对应的线段树合并,确保在后续查询时能够快速找到第k大权值。

技术实现

并查集部分

  • 并查集结构:使用路径压缩和按秩合并的优化方法,确保每次操作的时间复杂度较低。
  • 父节点数组:用于记录每个节点的父节点,路径压缩能有效降低查找时间。
  • 代表数组:用于存储每个集合的代表节点,避免多次查找相同父节点。
  • 线段树部分

  • 线段树节点结构:每个节点存储左、右子树指针以及区间的权值和。
  • 构建线段树:从1到n构建线段树,初始化每个节点的和。
  • 合并操作:在合并两个集合时,同时合并对应的线段树,使得查询操作能够快速获取第k大权值。
  • 查询操作:使用线段树的特性,快速定位第k大权值。
  • 代码解析

    线段树代码

    #include 
    using namespace std;#define mid ((l + r) >> 1)const int maxn = 1e5 + 5;int sum[maxn < 5], ls[maxn < 5], rs[maxn < 5], rt[maxn], tot;void pushup(int t) { int tl = ls[t], tr = rs[t]; sum[t] = sum[tl] + sum[tr];}int add(int l, int r, int t, int p, int c) { int now = ++tot; ls[now] = ls[t]; rs[now] = rs[t]; if (l == r) { sum[now] += c; return now; } if (p <= mid) { ls[now] = add(l, mid, ls[now], p, c); } else { rs[now] = add(mid + 1, r, rs[now], p, c); } pushup(now); return now;}int ask(int l, int r, int t, int k) { if (l == r) return l; if (sum[ls[t]] >= k) { return ask(l, mid, ls[t], k); } else { return ask(mid + 1, r, rs[t], k - sum[ls[t]]); }}int mer(int a, int b, int l, int r) { if (!a) return b; if (!b) return a; if (l == r) { sum[a] += sum[b]; return a; } ls[a] = mer(ls[a], ls[b], l, mid); rs[a] = mer(rs[a], rs[b], mid + 1, r); pushup(a); return a;}

    并查集代码

    int a[maxn], f[maxn], n, m, id[maxn];int getf(int x) {    return f[x] == x ? x : f[x] = getf(f[x]);}bool dsu_mer(int a, int b) {    int fa = getf(a), fb = getf(b);    if (fa == fb) return false;    f[fb] = fa;    mer(rt[fa], rt[fb], 1, n);    return true;}

    主函数

    int main() {    scanf("%d%d", &n, &m);    for (int i = 1; i <= n; i++) {        scanf("%d", a + i);        id[a[i]] = i;        f[i] = i;        rt[i] = add(1, n, rt[0], a[i], 1);    }    for (int i = 1; i <= m; i++) {        int x, y;        scanf("%d%d", &x, &y);        dsu_mer(x, y);    }    char op[5];    int q;    scanf("%d", &q);    for (int i = 1; i <= q; i++) {        scanf("%s", op);        scanf("%d%d", &x, &y);        if (op[0] == 'Q') {            x = getf(x);            if (sum[rt[x]] < y) {                printf("-1\n");            } else {                printf("%d\n", id[ask(1, n, rt[x], y)]);            }        } else {            dsu_mer(x, y);        }    }    return 0;}

    应用示例

    • 输入处理:读取n和m,然后初始化权值数组a。
    • 线段树构建:为每个节点构建线段树,记录每个节点的代表节点id。
    • 并查集操作:处理m次合并操作。
    • 查询操作:处理q次查询,返回第k大权值或-1。

    通过上述方法,我们可以在并查集合并过程中,高效地查询集合中的第k大权值。

    转载地址:http://gadi.baihongyu.com/

    你可能感兴趣的文章
    Nmap端口扫描工具Windows安装和命令大全(非常详细)零基础入门到精通,收藏这篇就够了
    查看>>
    NMAP网络扫描工具的安装与使用
    查看>>
    NMF(非负矩阵分解)
    查看>>
    nmon_x86_64_centos7工具如何使用
    查看>>
    NN&DL4.1 Deep L-layer neural network简介
    查看>>
    NN&DL4.3 Getting your matrix dimensions right
    查看>>
    NN&DL4.7 Parameters vs Hyperparameters
    查看>>
    NN&DL4.8 What does this have to do with the brain?
    查看>>
    nnU-Net 终极指南
    查看>>
    No 'Access-Control-Allow-Origin' header is present on the requested resource.
    查看>>
    NO 157 去掉禅道访问地址中的zentao
    查看>>
    no available service ‘default‘ found, please make sure registry config corre seata
    查看>>
    No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
    查看>>
    no connection could be made because the target machine actively refused it.问题解决
    查看>>
    No Datastore Session bound to thread, and configuration does not allow creation of non-transactional
    查看>>
    No fallbackFactory instance of type class com.ruoyi---SpringCloud Alibaba_若依微服务框架改造---工作笔记005
    查看>>
    No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalanc
    查看>>
    No mapping found for HTTP request with URI [/...] in DispatcherServlet with name ...的解决方法
    查看>>
    No mapping found for HTTP request with URI [/logout.do] in DispatcherServlet with name 'springmvc'
    查看>>
    No module named 'crispy_forms'等使用pycharm开发
    查看>>