思路

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

离线可以使用线段树分治,每个边按照存在的时间插入线段树的对应节点中,最后再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. Nginx技术研究系列1-通过应用场景看Nginx的反向代理

    随着我们业务规模的不断增长,整个系统规模由两年前的几十台服务器,井喷到现在2个数据中心,接近400台服务器,上百个WebApi站点,上百个域名. 这么多的WebApi站点这么多的域名,管理和维护成本很 ...

  2. Ngine X 完全开发指南 读书笔记-前言

    一开始接触的编程语言是VF,那是一种可视化编程语言,所谓的可视化,就是运行结果能直接看得到的,非常直观,便于调试,适合刚刚接触编程的新人学习.当时学得懵懂,半知半解,就是感觉程序非常神奇,常常几句代码 ...

  3. 每天记命令:lscpu 和 cat /proc/cpuinfo

    [1]lscpu lscpu命令,查看cpu相关的统计信息. socket 就是主板上插cpu的槽的数目,也就是可以插入的物理CPU的个数(比如上例,可以插入1个CPU). core 就是我们平时说的 ...

  4. K-Means算法的Java实现

    K-means算法是硬聚类算法,是典型的基于原型的目标函数聚类方法的代表,它是数据点到原型的某种距离作为优化的目标函数,利用函数求极值的方法得到迭代运算的调整规则.K-means算法以欧式距离作为相似 ...

  5. flask 对URL进行安全验证

    对URL进行安全验证 虽然我们已经实现了重定向会上一个页面的功能,但是安全问题不容忽视,鉴于referer和next容易被串篡改的特性,我们需要对这些值进行验证,否则会形成开放重定向漏洞   以URL ...

  6. Linux基础命令---文本显示od

    od 将指定文件的内容以八进制.十进制.十六进制等编码方式显示.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. 1.语法       ...

  7. C#获取驱动器盘符

    一.使用ManagementObjectSearcher类 static void Main(string[] args) { SelectQuery selectQuery = new Select ...

  8. bootsrtap h5 移动版页面 在苹果手机ios滑动上下拉动滚动卡顿问题解决方法

    bootsrtap h5 移动版页面 在苹果手机ios滑动上下拉动滚动卡顿问题解决方法 bootsrtap框架做的h5页面,在android手机下没有卡顿问题,在苹果手机就一直存在这问题,开始毫无头绪 ...

  9. Spring Batch 远程分区和远程分块的区别

    Partitioning is a master/slave step configuration that allows for partitions of data to be processed ...

  10. eclipse中的tomca的编辑页面server location灰色

    clipse中tomcat service设置 选择window ----show view---services可以看到服务的面板 双击tomcat进入配置界面Service Locations(S ...