线段树分治

其实思想说起来是比较简单的,我们把这个题里的所有操作(比如连边删边查询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;
}

线段树分治初步学习&洛谷P5227[AHOI2013]连通图的更多相关文章

  1. 李超线段树(segment[HEOI2013]-洛谷T4097)

    (neng了好久好久才糊弄懂得知识点...) 一.李超线段树 在线动态维护一个二维平面直角坐标系, 支持插入一条线段, 询问与直线x = x0相交的所有线段中,交点y的最大/小值 (若有多条线段符合条 ...

  2. 线段树板子1(洛谷P3372)

    传送 一道线段树板子(最简单的) 似乎之前在培训里写过线段树的样子?不记得了 何为线段树? 一般就是长成这样的树,树上的每个节点代表一个区间.线段树一般用于区间修改,区间查询的问题. 我们如何种写一棵 ...

  3. 洛谷.3733.[HAOI2017]八纵八横(线性基 线段树分治 bitset)

    LOJ 洛谷 最基本的思路同BZOJ2115 Xor,将图中所有环的异或和插入线性基,求一下线性基中数的异或最大值. 用bitset优化一下,暴力的复杂度是\(O(\frac{qmL^2}{w})\) ...

  4. Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)

    题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内 ...

  5. 【洛谷4219】[BJOI2014]大融合(线段树分治)

    题目: 洛谷4219 分析: 很明显,查询的是删掉某条边后两端点所在连通块大小的乘积. 有加边和删边,想到LCT.但是我不会用LCT查连通块大小啊.果断弃了 有加边和删边,还跟连通性有关,于是开始yy ...

  6. LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset

    题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...

  7. 洛谷 P2147 [SDOI2008]洞穴勘测 (线段树分治)

    题目链接 题解 早就想写线段树分治的题了. 对于每条边,它存在于一段时间 我们按时间来搞 我们可把一条边看做一条线段 我们可以模拟线段树操作,不断分治下去 把覆盖\(l-r\)这段时间的线段筛选出来, ...

  8. 【洛谷4585】[FJOI2015] 火星商店问题(线段树分治)

    点此看题面 大致题意: 有\(n\)家店,每个商品有一个标价.每天,都可能有某家商店进货,也可能有某人去购物.一个人在购物时,会于编号在区间\([L_i,R_i]\)的商店里挑选一件进货\(d_i\) ...

  9. 【洛谷P4319】 变化的道路 线段树分治+LCT

    最近学了一下线段树分治,感觉还蛮好用... 如果正常动态维护最大生成树的话用 LCT 就行,但是这里还有时间这一维的限制. 所以,我们就把每条边放到以时间为轴的线段树的节点上,然后写一个可撤销 LCT ...

随机推荐

  1. Array类型中的检测数组,转换方法,栈方法,队列方法

    我的新博客==> http://www.suanliutudousi.com/2017/08/24/array%E7%B1%BB%E5%9E%8B%E4%B8%AD%E7%9A%84%E6%A3 ...

  2. 21-Ubuntu-文件和目录命令-复制文件和目录-cp

    cp 将给出的文件或目录复制到另一个文件或目录,相当于DOS下的copy命令 选项 含义 -f 已经存在的目标文件直接覆盖,不提示 -i 覆盖文件前提示 -r 若给出的源文件是目录文件,则cp将递归复 ...

  3. mysql 06章_分组查询和链接查询

    一.分组查询 在进行查询时,通常需要按某个或某些字段进行一些统计,因此就需要使用分组查询,但分组后通常需要与聚合函数使用,分组才有意义. 语法:SELECT <字段列表|*> FROM 表 ...

  4. Win10下使用默认的照片查看器

    在打开图片的时候默认是 画图,我们想要用windows图片器打开,但是更多应用里面没有这一选项, 按 Windows徽标键+R键,打开运行命令窗口,输入"regedit"命令 来打 ...

  5. Let's Encryt免费SSL证书申请[我司方案]

    Let's Encrypt颁发的证书是目前生产的大多数浏览器都信任的,您只需下载并运行Let's Encrypt客户端来生成一个证书即可. 在颁发证书之前,需要验证您的域名的所有权.首先,在您的主机上 ...

  6. php 数据导出到excel 2种带有合并单元格的导出

    具体业务层面 可能会有所不同.以下两种方式涉及的合并单元格地方有所不同,不过基本思路是一致的. 第一种是非插件版本.可能更容易理解点,基本思路就是 组装table 然后 读取 输出到excel上.缺点 ...

  7. thinkphp 模板注释

    模板支持注释功能,该注释文字在最终页面不会显示,仅供模板制作人员参考和识别. 大理石平台厂家 单行注释 格式: {/* 注释内容 */ } 或 {// 注释内容 } 例如: {// 这是模板注释内容 ...

  8. Linq Lambda 中group by多列后count数量的写法

    直接上代码: List<Student> ss = new List<Student>(); Student ss1 = , Age = , Name = " }; ...

  9. Delphi THashedStringList用法

    Delphi中的THashedStringList对象 Delphi在在IniFiles 单元中定义了THashedStringList类: THashedStringList = class(TSt ...

  10. Java 11 发布计划来了,已确定 3个 新特性!!

    Oracle 已经发布了 Java Development Kit 10,下一个版本 JDK 11 也在准备之中了.按照 Java 新的版本发布标准,Java 11 将在 6 个月后到来,现在它还只有 ...