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

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<\'0\'||c>\'9\') {if (c==\'-\') f=-1;c=getchar();}
    while (c>=\'0\'&&c<=\'9\') x=(x<<1)+(x<<3)+(c^48),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[2],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^=1;}
void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=0;}
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=0;k;t=k,k=tree[k].fa) splay(k),tree[k].ch[1]=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[0]=tree[x].fa=0;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=1;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==0) f[1ll*q[i].x*m+q[i].y]=i;
        if (q[i].op==1) q[f[1ll*q[i].x*m+q[i].y]].del=i;
    }
    cnt=n;
    for (int i=0;i<=n;i++) tree[i].s=i,v[i]=M;
    for (int i=1;i<=m;i++) if (q[i].op==0&&q[i].del==0) q[i].del=M;
    for (int i=1;i<=m;i++)
    if (q[i].op==0)
    {
        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==2)
    {
        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 0;
}

 

版权声明:本文为Gloid原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/Gloid/p/9383875.html