线段树分治初步学习&洛谷P5227[AHOI2013]连通图

线段树分治

其实思想说起来是比较简单的,我们把这个题里的所有操作(比如连边删边查询balabala)全部拍到一棵线段树上,然后对着整棵树dfs一下求解答案,顺便把操作做一下,回溯的时候撤销一下即可。虽然有的操作需要以区间形式拍到树上,导致它可能会被拆成两个,但线段树的形态同样保证了操作最多只会被拆分\(log(区间长度)\)次,保障了复杂度。

洛谷P5227[AHOI2013]连通图

传送门

其实就是线段树分治+带撤销并查集,并查集写按秩合并,不能路径压缩(否则会破坏结构,就会撤销出奇怪的效果)
以询问的时间轴为下标建一棵线段树,然后把边存在的时间区间拍到线段树上,用\(vector\)存下来,再对着树一波\(dfs\)记录答案,注意在叶节点不能写\(return\)我沙茶了,不然叶节点如果有操作就会还没撤销就返回了。
md没有板对着敲自己yy着写好难受,码了一天

/*P5227 [AHOI2013]连通图*/  
#include <bits/stdc++.h>
#define N (100000 + 5)
using namespace std;
inline int read() {
    int cnt = 0, f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
    while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + c - '0'; c = getchar();}
    return cnt * f;
}
int n, m, k, c, x, top;
int fa[N];
struct node {
    int u, v;
}edge[N << 1];
struct node2 {
    int siz, dep, fa;
    node2(int siz_ = 1, int dep_ = 1, int fa_ = 0) : siz(siz_), dep(dep_), fa(fa_){};
}bcj[N << 1], ctrl_Z[N << 1];
int cur[N << 1], top2;
int pre[N << 1];
int get_father(int x) {return x == bcj[x].fa ? x : get_father(bcj[x].fa);}
void merge(int p, int q) {
    int x = get_father(p), y = get_father(q);
    if (x == y) return;
    if (bcj[x].dep > bcj[y].dep) swap(x, y);
    ctrl_Z[++top] = bcj[x];
    ctrl_Z[++top] = bcj[y];
    bcj[x].fa = y, bcj[y].dep = max(bcj[y].dep, bcj[x].dep + 1), bcj[y].siz += bcj[x].siz;
    cur[++top2] = x;
    cur[++top2] = y;
}
struct node3{
    int l, r;
    vector<node> E;
    #define l(p) tree[p].l
    #define r(p) tree[p].r
}tree[N << 2];

void build(int l, int r, int p) {
    l(p) = l, r(p) = r;
    if (l == r) return;
    int mid = (l + r) >> 1;
    build (l, mid, p << 1);
    build (mid + 1, r, p << 1 | 1);
}

void insert(node x, int l, int r, int p) {
    if (l <= l(p) && r >= r(p)) { tree[p].E.push_back(x); return; }
    register int mid = (l(p) + r(p)) >> 1;
    if (l <= mid) insert(x, l, r, p << 1);
    if (r > mid) insert(x, l, r, p << 1 | 1);
}
void dfs_(int p) {
    int tp = top2;
    for (register unsigned int i = 0; i < tree[p].E.size(); i++) {
        node now = tree[p].E[i];
        merge(now.u, now.v);
    }
    if (l(p) == r(p)) {
        int now = bcj[get_father(1)].siz;
        printf(now == n ? "Connected\n" : "Disconnected\n");
    } else dfs_(p << 1), dfs_(p << 1 | 1);
    for (; top2 > tp; --top2, --top) {bcj[cur[top2]] = ctrl_Z[top];}
}

int main() {
    n = read(), m = read();
    for (register int i = 1; i <= n; i++) bcj[i] = node2(1, 1, i);
    for (register int i = 1; i <= m; i++) 
        edge[i].u = read(), edge[i].v = read(), pre[i] = 1;
    k = read();
    build (1, k, 1);
    for (register int i = 1; i <= k; i++) {
        c = read();
        for (register int j = 1; j <= c; j++) {
            x = read();
            if (pre[x] < i) insert(edge[x], pre[x], i - 1, 1);
            pre[x] = i + 1;
        }
    }
    for (register int i = 1; i <= m; i++) {
        if (pre[i] <= k) insert(edge[i], pre[i], k, 1);
    }
    dfs_(1);
    return 0;
} 

转载于:https://www.cnblogs.com/kma093/p/11275762.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值