• codeforces 466E


    我们考虑离线,把第三种操作挂在第二种上,那么我们只需要查询对应时刻的森林中某个点是不是当前操作点的祖先即可

    因为只有加边操作,我们把森林的祖先后代关系变成判断他在离线的最终树上的祖先后代关系和判断两点是否连通

    并查集维护连通性,LCA查询祖先后代关系

    复杂度(O(m log n))

     1 #include<bits/stdc++.h>
     2 #define maxn 100005
     3 using namespace std;
     4 int n,m;
     5 struct Opt
     6 {
     7     int op,x,y;
     8     Opt(int OP=0,int X=0,int Y=0):op(OP),x(X),y(Y){}
     9 }opt[maxn];
    10 vector< pair<int,int> > qry[maxn];
    11 int Ans[maxn];
    12 int m1,m2;
    13 int fa[maxn];
    14 int find(int x){if(fa[x]==x)return x;else return fa[x]=find(fa[x]);}
    15 vector<int> g[maxn];
    16 bool isroot[maxn];
    17 int anc[maxn][20],d[maxn];
    18 void dfs(int u)
    19 {
    20     for(int v:g[u])
    21     {
    22         d[v]=d[u]+1;anc[v][0]=u;
    23         dfs(v);
    24     }
    25 }
    26 int LCA(int u,int v)
    27 {
    28     if(d[u]<=d[v])swap(u,v);
    29     for(int i=18;i>=0;--i)if(d[anc[u][i]]>=d[v])u=anc[u][i];
    30     if(u==v)return u;
    31     for(int i=18;i>=0;--i)if(anc[u][i]!=anc[v][i])u=anc[u][i],v=anc[v][i];
    32     return anc[u][0];
    33 }
    34 int main()
    35 {
    36     scanf("%d%d",&n,&m);
    37     for(int i=1;i<=n;++i)fa[i]=i,isroot[i]=1;
    38     for(int i=1;i<=m;++i)
    39     {
    40         int t,x,y;
    41         scanf("%d%d",&t,&x);
    42         if(t!=2)scanf("%d",&y);
    43         if(t==1)opt[++m1]=Opt(t,x,y),g[y].push_back(x),isroot[x]=0;
    44         if(t==2)opt[++m1]=Opt(t,x);
    45         if(t==3)qry[y].push_back(make_pair(x,++m2));
    46     }
    47     for(int i=1;i<=n;++i)if(isroot[i])g[0].push_back(i);
    48     dfs(0);
    49     for(int j=1;j<=18;++j)
    50         for(int i=1;i<=n;++i)anc[i][j]=anc[anc[i][j-1]][j-1];
    51     int id=0;
    52     for(int i=1;i<=m1;++i)
    53     {
    54         int t,x,y;
    55         t=opt[i].op,x=opt[i].x,y=opt[i].y;
    56         if(t==1)
    57         {
    58             if(find(x)!=find(y))fa[find(x)]=find(y);
    59         }
    60         if(t==2)
    61         {
    62             ++id;
    63             for(auto pa:qry[id])
    64             {
    65                 int u=x,v=pa.first;
    66                 if(LCA(u,v)==v&&find(u)==find(v))Ans[pa.second]=1;
    67                 else Ans[pa.second]=0;
    68             }
    69         }
    70     }
    71     for(int i=1;i<=m2;++i)if(Ans[i])puts("YES");else puts("NO");
    72 }
    View Code
  • 相关阅读:
    integer比较
    String比较
    StringBuffer的s1.capacity()是多少?
    时间复杂度
    京东面试--总结
    说下Java堆空间结构,及常用的jvm内存分析命令和工具
    linux下jmap,jstat和jstack使用
    jvm 性能调优工具之 jmap
    jstack(查看线程)、jmap(查看内存)和jstat(性能分析)命令
    android小技巧:在activity中实现与绑定的fragment的回调
  • 原文地址:https://www.cnblogs.com/uuzlove/p/12292044.html
Copyright © 2020-2023  润新知