用LCT维护一下删除时间的最大生成树即可。当然也可以线段树分治。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 5010
#define M 500010
#define lson tree[k].ch[0]
#define rson tree[k].ch[1]
#define lself tree[tree[k].fa].ch[0]
#define rself tree[tree[k].fa].ch[1]
int n,m,x[N+M],y[N+M],v[N+M],cnt;
map<long long,int> f;
struct edge{int op,x,y,del;
}q[M];
struct data{int ch[],fa,rev,s;
}tree[N+M];
void up(int k)
{
tree[k].s=k;
if (v[tree[lson].s]<v[k]) tree[k].s=tree[lson].s;
if (v[tree[rson].s]<v[tree[k].s]) tree[k].s=tree[rson].s;
}
void rev(int k){if (k) swap(lson,rson),tree[k].rev^=;}
void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=;}
bool isroot(int k){return lself!=k&&rself!=k;}
int whichson(int k){return rself==k;}
void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);}
void move(int k)
{
int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k);
if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf;
tree[fa].ch[p]=tree[k].ch[!p],tree[tree[k].ch[!p]].fa=fa;
tree[k].ch[!p]=fa,tree[fa].fa=k;
up(fa),up(k);
}
void splay(int k)
{
push(k);
while (!isroot(k))
{
int fa=tree[k].fa;
if (!isroot(fa))
if (whichson(fa)^whichson(k)) move(k);
else move(fa);
move(k);
}
}
void access(int k){for (int t=;k;t=k,k=tree[k].fa) splay(k),tree[k].ch[]=t,up(k);}
void makeroot(int k){access(k),splay(k),rev(k);}
int findroot(int k){access(k),splay(k);for (;lson;k=lson) down(k);splay(k);return k;}
void link(int x,int y){makeroot(x);tree[x].fa=y;}
void cut(int x,int y){makeroot(x),access(y),splay(y);tree[y].ch[]=tree[x].fa=;up(y);}
int query(int x,int y){makeroot(x),access(y),splay(y);return tree[y].s;}
void newpoint(int p,int q,int z)
{
cnt++;tree[cnt].s=cnt;v[cnt]=z;
x[cnt]=p,y[cnt]=q;
link(cnt,p),link(cnt,q);
}
int main()
{
freopen("dynamic_graph.in","r",stdin);
freopen("dynamic_graph.out","w",stdout);
n=read(),m=read();
for (int i=;i<=m;i++)
{
q[i].op=read(),q[i].x=read(),q[i].y=read();
if (q[i].x>q[i].y) swap(q[i].x,q[i].y);
if (q[i].op==) f[1ll*q[i].x*m+q[i].y]=i;
if (q[i].op==) q[f[1ll*q[i].x*m+q[i].y]].del=i;
}
cnt=n;
for (int i=;i<=n;i++) tree[i].s=i,v[i]=M;
for (int i=;i<=m;i++) if (q[i].op==&&q[i].del==) q[i].del=M;
for (int i=;i<=m;i++)
if (q[i].op==)
{
if (findroot(q[i].x)!=findroot(q[i].y)) newpoint(q[i].x,q[i].y,q[i].del);
else
{
int t=query(q[i].x,q[i].y);
if (v[t]<q[i].del)
{
cut(t,x[t]),cut(t,y[t]);
newpoint(q[i].x,q[i].y,q[i].del);
}
}
}
else if (q[i].op==)
{
if (findroot(q[i].x)!=findroot(q[i].y)||v[query(q[i].x,q[i].y)]<i) printf("N\n");
else printf("Y\n");
}
fclose(stdin);fclose(stdout);
return ;
}

LOJ121 动态图连通性(LCT)的更多相关文章

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

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

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

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

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

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

  4. LOJ121 「离线可过」动态图连通性

    思路 动态图连通性的板子,可惜我不会在线算法 离线可以使用线段树分治,每个边按照存在的时间插入线段树的对应节点中,最后再dfs一下求出解即可,注意并查集按秩合并可以支持撤销操作 由于大量使用STL跑的 ...

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

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

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

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

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

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

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

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

  9. LOJ.121.[离线可过]动态图连通性(线段树分治 按秩合并)

    题目链接 以时间为下标建线段树.线段树每个节点开个vector. 对每条边在其出现时间内加入线段树,即,把这条边按时间放在线段树的对应区间上,会影响\(O(\log n)\)个节点. 询问就放在线段树 ...

随机推荐

  1. 如何计算PCB设计中的阻抗

    关于阻抗的话题已经说了这么多,想必大家对于阻抗控制在pcb layout中的重要性已经有了一定的了解.俗话说的好,工欲善其事,必先利其器.要想板子利索的跑起来,传输线的阻抗计算肯定不能等闲而视之. 在 ...

  2. 微信小程序开发需要注意的30个坑

    1.小程序名称可以由中文.数字.英文.长度在3-20个字符之间,一个中文字等于2个字符. 2.小程序名称不得与公众平台已有的订阅号.服务号重复.如提示重名,请更换名称进行设置. 3.小程序名称在帐号信 ...

  3. IDC Digital Transition Annual Festival(2018.10.19)

    时间:2018.10.19地点:北京万达文化酒店

  4. [Oracle][Partition][Controlfile]Partition 操作是否和 Controlfile有关?

    Partition 操作是否和 Controlfile有关? 通过实验来判断: 对比 Partition 前后的操作,看看controlfile 的dump 信息中是否有记录,结果发现没有记录在 co ...

  5. [Python]Python 函数调用小例子

    函数定义: In [78]: def printme(str): ....: print str ....: return ....: 调用: In [79]: printme('This is Ji ...

  6. python基础学习笔记(六)

    学到这里已经很不耐烦了,前面的数据结构什么的看起来都挺好,但还是没法用它们做什么实际的事. 基本语句的更多用法 使用逗号输出 >>> print 'age:',25 age: 25 ...

  7. EnglishGame

    https://github.com/zhangxue520/EnglishGame/blob/master/EnglishGame <程序设计实践I> 题目:       打字训练测试软 ...

  8. 转角遇见——Software

    第一部分:结缘计算机 从五岁开始读书,懵懵懂懂,从小就听长辈们说一定要考一个好大学,高三老师们就更是说:“过了高考,人生就无忧了”.于是似乎,高考就好像是我自出生以来这么多年的唯一愿景.高考成绩下来后 ...

  9. shell脚本--shift参数左移

    参数左移什么意思呢?这个参数指的是在运行脚本时,跟在脚本名后面的参数,前面已经讲过,可以使用$#来获取参数的个数,使用$*来获取所有的参数,而参数左移的含义是这样的:有个指针指向参数列表第一个参数,左 ...

  10. PAT 1002 写出这个数

    https://pintia.cn/problem-sets/994805260223102976/problems/994805324509200384 读入一个自然数n,计算其各位数字之和,用汉语 ...