LOJ.121.[离线可过]动态图连通性(线段树分治 按秩合并)
以时间为下标建线段树。线段树每个节点开个vector。
对每条边在其出现时间内加入线段树,即,把这条边按时间放在线段树的对应区间上,会影响\(O(\log n)\)个节点。
询问就放在线段树的对应叶子节点上。
然后对整棵树DFS,当进入一个节点时,将这个点代表的这段区间中出现的边全部加到图里,即合并起来,之后在离开这个点时撤销。
可以用不路径压缩、按秩合并的并查集维护连通性。这样就可以撤销了。
合并时用栈记录合并前状态,合并前的父节点用\(x\)或是\(fa[x]\)都行,因为合并的时候是合并集合根节点,用\(x\)还是\(fa[x]\)都一样。。
如果秩改变也要加入栈。
启发式合并按深度还是按size无所谓。
//1548ms 48256K
#include <map>
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
#define mp std::make_pair
#define pr std::pair<int,int>
#define Vec std::vector<int>
//#define gc() getchar()
#define MAXIN 500000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=5005,M=5e5+5;
int n,m,fa[N],dep[N],top;
std::map<pr,int> las;
char IN[MAXIN],*SS=IN,*TT=IN;
struct Node
{
int x,dep;
}sk[M<<1];//M就够吧。。
struct Operation
{
int id,u,v;
}opt[M];
struct Segment_Tree
{
#define lson rt<<1
#define rson rt<<1|1
std::vector<int> vec[M<<2];
void Update(int l,int r,int rt,int L,int R,int id)
{
if(L<=l && r<=R) return (void)vec[rt].push_back(id);
int m=l+r>>1;
if(L<=m) Update(l,m,rt<<1,L,R,id);
if(m<R) Update(m+1,r,rt<<1|1,L,R,id);
}
}T;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
int Get_fa(int x){
return x==fa[x]?x:Get_fa(fa[x]);
}
inline void Merge(int x,int y)
{
if((x=Get_fa(x))==(y=Get_fa(y))) return;
if(dep[y]>dep[x]) std::swap(x,y);//y->x
fa[y]=x, sk[++top]=(Node){y,dep[y]};
if(dep[x]==dep[y]) sk[++top]=(Node){x,dep[x]++};
}
inline void Delete(int bef)
{
while(top>bef)
{
int x=sk[top].x;
fa[x]=x, dep[x]=sk[top--].dep;
}
}
void DFS(int l,int r,int rt)
{
int now=top;
const Vec &v=T.vec[rt];
for(int i=0,lim=v.size(); i<lim; ++i) Merge(opt[v[i]].u,opt[v[i]].v);
if(l==r){
if(opt[l].id==2)//询问直接在叶节点上
putchar(Get_fa(opt[l].u)==Get_fa(opt[l].v)?'Y':'N'),putchar('\n');
}
else DFS(l,l+r>>1,lson), DFS((l+r>>1)+1,r,rson);
Delete(now);
}
int main()
{
n=read(), m=read();
for(int i=1; i<=n; ++i) fa[i]=i;
std::map<pr,int>::iterator it;
for(int id,x,y,i=1; i<=m; ++i)
{
id=read(), x=read(), y=read();
if(x>y) std::swap(x,y);
if(!id) las[mp(x,y)]=i;
else if(id==1) it=las.find(mp(x,y)), T.Update(1,m,1,it->second,i,i), it->second=0;//包含不包含i无所谓了,i处已不是询问
opt[i]=(Operation){id,x,y};
}
for(it=las.begin(); it!=las.end(); ++it)
if(it->second) T.Update(1,m,1,it->second,m,it->second);
DFS(1,m,1);
return 0;
}
LOJ.121.[离线可过]动态图连通性(线段树分治 按秩合并)的更多相关文章
- LOJ#121. 「离线可过」动态图连通性(线段树分治)
题意 板子题,题意很清楚吧.. Sol 很显然可以直接上LCT.. 但是这题允许离线,于是就有了一个非常巧妙的离线的做法,好像叫什么线段树分治?? 此题中每条边出现的位置都可以看做是一段区间. 我们用 ...
- loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)
题意 题目链接 Sol 线性基+线段树分治板子题.. 调起来有点自闭.. #include<bits/stdc++.h> #define fi first #define se secon ...
- LOJ 121 「离线可过」动态图连通性——LCT维护删除时间最大生成树 / 线段树分治
题目:https://loj.ac/problem/121 离线,LCT维护删除时间最大生成树即可.注意没有被删的边的删除时间是 m+1 . 回收删掉的边的节点的话,空间就可以只开 n*2 了. #i ...
- [LOJ#121]动态图连通性
[LOJ#121]动态图连通性 试题描述 这是一道模板题. 你要维护一张无向简单图.你被要求加入删除一条边及查询两个点是否连通. 0:加入一条边.保证它不存在. 1:删除一条边.保证它存在. 2:查询 ...
- 【LOJ121】「离线可过」动态图连通性
[LOJ121]「离线可过」动态图连通性 题面 LOJ 题解 线段树分治的经典应用 可以发现每个边出现的时间是一个区间 而我们每个询问是一个点 所以我们将所有边的区间打到一颗线段树上面去 询问每个叶子 ...
- LOJ121 「离线可过」动态图连通性
思路 动态图连通性的板子,可惜我不会在线算法 离线可以使用线段树分治,每个边按照存在的时间插入线段树的对应节点中,最后再dfs一下求出解即可,注意并查集按秩合并可以支持撤销操作 由于大量使用STL跑的 ...
- [基本操作]线段树分治和动态dp
不知道为什么要把这两个没什么关系的算法放到一起写...可能是都很黑科技? 1.线段树分治 例题:bzoj4026 二分图 给你一个图,资瓷加一条边,删一条边,询问当前图是不是二分图 如果用 LCT 的 ...
- 【离线 撤销并查集 线段树分治】bzoj1018: [SHOI2008]堵塞的交通traffic
本题可化成更一般的问题:离线动态图询问连通性 当然可以利用它的特殊性质,采用在线线段树维护一些标记的方法 Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常 ...
- LOJ 2585 「APIO2018」新家 ——线段树分治+二分答案
题目:https://loj.ac/problem/2585 算答案的时候要二分! 这样的话,就是对于询问位置 x ,二分出一个最小的 mid 使得 [ x-mid , x+mid ] 里包含所有种类 ...
随机推荐
- 用matplotlib绘制每次交易的盈亏三角形
用matplotlib绘制每次交易的盈亏三角形 结果: 代码: python def plot_trade_triangle(self): # plot each trade as a trade-t ...
- Java SpringMVC框架学习(三)springMVC的执行流程
具体执行逻辑如下: 浏览器提交请求到中央调度器. 中央调度器将请求转给处理器映射器. 处理器映射器根据请求, 找到请求对应的处理器, 并将其封装为处理器执行链返回给中央调度器. 中央调度器根据处理器执 ...
- 仿QQ聊天图文混排流程图【适用于XMPP】
图文混排流程图.graffle4.8 KB 下面附上图片素材: 表情.zip692.5 KB 下面是字符串与图片的详细对应关系: "[呲牙]& ...
- XMPP用户登录
CHENYILONG Blog XMPP用户登录 技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博http://weibo.com/luohanchenyilon ...
- [python]使用python实现Hadoop MapReduce程序:计算一组数据的均值和方差
这是参照<机器学习实战>中第15章“大数据与MapReduce”的内容,因为作者写作时hadoop版本和现在的版本相差很大,所以在Hadoop上运行python写的MapReduce程序时 ...
- laravel一个页面两个表格分页处理
关键是看懂laravel自带的 paginate() 方法. 在Builder.php文件(项目名称/laravel/vendor/laravel/framework/src/Illuminate/D ...
- 洛谷 P1525 【关押罪犯】种类并查集
题解 P1525 [关押罪犯]:种类并查集 前言: 在数据结构并查集中,种类并查集属于扩展域并查集一类. 比较典型的题目就是:食物链(比本题难一些,有三个种类存在) 首先讲一下本题的贪心,这个是必须要 ...
- caoha
- 【SVN】SVN的trunk、branches、tag的使用以及分支的概念
SVN命令参考: https://www.cnblogs.com/wlsxmhz/p/5775393.html svn的存储结构一般建议在根目录下建立trunk.branches.tags这三个文 ...
- python运行execjs解密js
[转]http://www.knowsky.com/1041161.html python 记一次计算qzonetoken经历 之前用python写了个发表说说的爬虫,但最近发现在post数据时返回不 ...