思路

动态图连通性的板子,可惜我不会在线算法

离线可以使用线段树分治,每个边按照存在的时间插入线段树的对应节点中,最后再dfs一下求出解即可,注意并查集按秩合并可以支持撤销操作

由于大量使用STL跑的很慢的代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#include <set>
#include <map>
const int MAXN = 5101;
const int MAXM = 500100;
using namespace std;
int n,timex=0,m,ans[MAXM],cnt;
struct Udsu{
int h[MAXN],fa[MAXN];
stack<int> mer,height;
int find(int x){
if(fa[x]==x)
return x;
else
return find(fa[x]);
}
bool query(int x,int y){
return find(x)==find(y);
}
void merge(int x,int y){
x=find(x);
y=find(y);
if(h[x]<=h[y]){
mer.push(x);
fa[x]=y;
if(h[x]==h[y]){
h[y]++;
height.push(1);
}
else
height.push(0);
}
else{
mer.push(y);
fa[y]=x;
height.push(0);
}
}
void undo(void){
int x=mer.top();
mer.pop();
int val=height.top();
height.pop();
h[fa[x]]-=val;
fa[x]=x;
}
void init(void){
for(int i=1;i<=n;i++)
h[i]=1,fa[i]=i;
}
}DSU;
struct edge{
int u,v;
bool operator < (const edge &b) const{
return u<b.u||(u==b.u&&v<b.v);
}
};
struct Node{
int le,u,v;//-1 add else query
bool operator < (const Node &b) const{
return le<b.le;
}
};
map<edge,int> M;
vector<Node> seg[MAXM<<2];
void add(int l,int r,int L,int R,int o,int le,int u,int v){
// printf("add l=%d r=%d L=%d R=%d o=%d\n",l,r,L,R,o);
// Sleep(700);
if(L<=l&&r<=R){
seg[o].push_back((Node){le,u,v});
return;
}
int mid=(l+r)>>1;
if(L<=mid)
add(l,mid,L,R,o<<1,le,u,v);
if(R>mid)
add(mid+1,r,L,R,o<<1|1,le,u,v);
}
void dfs(int l,int r,int o){
// printf("l=%d r=%d o=%d\n",l,r,o);
sort(seg[o].begin(),seg[o].end());
for(int i=0;i<seg[o].size();i++){
if(seg[o][i].le==-1){
DSU.merge(seg[o][i].u,seg[o][i].v);
// printf("link %d %d\n",seg[o][i].u,seg[o][i].v);
}
else{
ans[seg[o][i].le]=DSU.query(seg[o][i].u,seg[o][i].v);
// printf("query %d %d\n",seg[o][i].u,seg[o][i].v);
}
}
if(l!=r){
int mid=(l+r)>>1;
dfs(l,mid,o<<1);
dfs(mid+1,r,o<<1|1);
}
for(int i=0;i<seg[o].size();i++)
if(seg[o][i].le==-1){
// printf("undo\n");
DSU.undo();
}
}
int main(){
scanf("%d %d",&n,&m);
DSU.init();
for(int i=1;i<=m;i++){
++timex;
int opt,u,v;
scanf("%d %d %d",&opt,&u,&v);
if(u>v)
swap(u,v);
if(opt==0){
M[((edge){u,v})]=timex;
}
if(opt==1){
// printf("addtime=%d endtime=%d\n",M[((edge){u,v})],timex);
add(1,m+1,M[((edge){u,v})],timex,1,-1,u,v);
M.erase((edge){u,v});
}
if(opt==2){
add(1,m+1,timex,timex,1,++cnt,u,v);
}
}
++timex;
for(map<edge,int>::iterator it=M.begin();it!=M.end();it++){
add(1,m+1,(*it).second,m+1,1,-1,(*it).first.u,(*it).first.v);
}
dfs(1,m+1,1);
for(int i=1;i<=cnt;i++){
printf("%s\n",(ans[i])?"Y":"N");
}
return 0;
}

LOJ121 「离线可过」动态图连通性的更多相关文章

  1. 【LOJ121】「离线可过」动态图连通性

    [LOJ121]「离线可过」动态图连通性 题面 LOJ 题解 线段树分治的经典应用 可以发现每个边出现的时间是一个区间 而我们每个询问是一个点 所以我们将所有边的区间打到一颗线段树上面去 询问每个叶子 ...

  2. LOJ 121 「离线可过」动态图连通性——LCT维护删除时间最大生成树 / 线段树分治

    题目:https://loj.ac/problem/121 离线,LCT维护删除时间最大生成树即可.注意没有被删的边的删除时间是 m+1 . 回收删掉的边的节点的话,空间就可以只开 n*2 了. #i ...

  3. LOJ#121. 「离线可过」动态图连通性(线段树分治)

    题意 板子题,题意很清楚吧.. Sol 很显然可以直接上LCT.. 但是这题允许离线,于是就有了一个非常巧妙的离线的做法,好像叫什么线段树分治?? 此题中每条边出现的位置都可以看做是一段区间. 我们用 ...

  4. LOJ #121. 「离线可过」动态图连通性 LCT维护最大生成树

    这个还是比较好理解的. 你考虑如果所有边构成一棵树的话直接用 LCT 模拟一波操作就行. 但是可能会出现环,于是我们就将插入/删除操作按照时间排序,然后依次进行. 那么,我们就要对我们维护的生成树改变 ...

  5. 【LOJ】#121. 「离线可过」动态图连通性

    题解 和BZOJ4025挺像的 就是维护边权是时间的最大生成树 删边直接删 两点未联通时直接相连,两点联通则找两点间边权小的一条边删除即可 代码 #include <bits/stdc++.h& ...

  6. loj#121.「离线可过」动态图连通性

    题面 话说#122怎么做啊 题解 我的\(\mathrm{LCT}\)水平极差,连最小生成树都快忘了,赶紧复习一下 做法和这篇是一样的 这道题还可以练习线段树分治 还可以练习ETT 果然是道吼题 代码 ...

  7. 「LOJ 121」「离线可过」动态图连通性「按时间分治 」「并查集」

    题意 你要维护一张\(n\)个点的无向简单图.你被要求执行\(m\)条操作,加入删除一条边及查询两个点是否连通. 0:加入一条边.保证它不存在. 1:删除一条边.保证它存在. 2:查询两个点是否联通. ...

  8. LOJ121 【离线可过】动态图连通性

    题目链接:戳我 [线段树分治版本代码] 这里面的线段树是时间线段树,每一个节点都要开一个vector,记录当前时间区间中存在的边的标号qwq #include<iostream> #inc ...

  9. [LOJ#121]动态图连通性

    [LOJ#121]动态图连通性 试题描述 这是一道模板题. 你要维护一张无向简单图.你被要求加入删除一条边及查询两个点是否连通. 0:加入一条边.保证它不存在. 1:删除一条边.保证它存在. 2:查询 ...

随机推荐

  1. Yii2 Restful api搜索实现

  2. Helter Skelter (扫描线 + 离散化 + 树状数组)

    扫描线:按照其中一个区间的标记为pos,然后左区间标记d为正影响,有区间标记d为负影响,然后根据所有的pos排序.pos从小扫到大,那么对于某一个区间一定会被扫过2次,那么经过2次之后就只剩下中间那一 ...

  3. Subway (树中心 + 树hash)

    首先找到树的中心或者中心,我这里是找中心,因为我们需要找一个相同的起点,然后最多2个中心就是树的宽度为偶数时,奇数时为1个. 找到之后需要对树进行hash,使得每个点都具备独特性,使之树的形态能够保证 ...

  4. QString 与 string转换

    [1]QString 转换为string QString qString("好好学习天天向上"); std::string stdString = qString.toStdStr ...

  5. python seek()方法报错:“io.UnsupportedOperation: can't do nonzero cur-relative seeks”

    今天使用seek()时报错了, 看下图 然后就百度了一下,找到了解决方法 这篇博客https://www.cnblogs.com/xisheng/p/7636736.html 帮忙解决了问题, 照理说 ...

  6. centos-ftp搭建

    参照https://blog.csdn.net/a735834365/article/details/80622105 https://blog.csdn.net/a735834365/article ...

  7. Qt读取TXT文件时,GBK与UTF-8编码判断

    读取txt文件时,很多时候无法获取文件的编码格式.如果直接进行使用,则有可能出现乱码.需要在使用前将其转为Unicode(Qt的默认编码格式). 虽然实际的编码格式种类非常多,但平常主要使用的有GBK ...

  8. C++中虚函数的作用

    一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始) 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数.虚函数的作用,用专业术语来解释就是实现多态性(Po ...

  9. 笔面试复习(spring常用.jar包/事务/控制反转/bean对象管理和创建/springMVC工作原理/sql查询)

    ###spring常用jar包1.spring.jar是包含有完整发布模块的单个jar包.2.org.springframework.aop包含在应用中使用Spring的AOP特性时所需要的类.3.o ...

  10. linux操作文件和文件夹

    rm filerm -rf folder如将/test1目录下的file1复制到/test3目录,并将文件名改为file2,可输入以下命令:cp /test1/file1 /test3/file2 如 ...