zoukankan      html  css  js  c++  java
  • 离线可持久化动态树

      不,你想多了,我并没有发明.  


      动态树?我会LCT!

      然后加上在线和可持久化的前缀,这道题就变得面目可憎了起来.

      对于一个森林,刚开始没有边.你需要维护下面的操作.

      操作1:给定x,y,令x的父亲为y.

      操作2:给定t,x,k,求第t个版本中x的第k个祖先.如果没有输出0.

      操作3:给定t,x,求第t个版本中x的深度.

      20%:n<=100,m<=500,强制在线.

      另外30%:不强制在线.

      100%:n<=100000,m<=500000,有可能强制在线.  


      那么只说一下离线的好了.

      这拿头写啊?看下面的题了.然后发现下面的题更难.于是回来想这道怎么做.

      20分貌似很好拿.维护每个版本每个节点的父亲,每个询问就O(n)的往上跳就完事了.

      然后开始剩下的70分怎么办.想到了想LCT,但是可持久化解决不了.LCT一会拆开一会旋转的,不好搞.我还会什么数据结构呢?我会树链剖分!于是离线的30分就有了:先做出来最后的树的树链.用线段树维护树链区间的下标和最大时间戳.跑的时候,如果"版本号"<时间戳就不能过去,递归一个子区间即可.很稳的mlogn^2.

      开始写的时候,我想到,我只需要维护区间最大时间戳,为什么不写递增呢?

      先全部读入,用倍增的思想预处理出每个节点x的第2^k祖先fa[x][k]和这条路径上的最大时间戳maxx[x][k].每次询问就每次开开心心的跳就完事了.

    using namespace std;
    int n;
    namespace _20
    {
        int m,x,tx,ty,fa[110][500010],u,t,ans,op,k;
        int lastans;    
    }
    namespace _30
    {
        int m;
        struct ASK
        {
            int op,t,u,k;
        }o[500010];
        int t,tx,ty,k,u;
        int fa[100010][25],maxx[100010][25];
    }
    int main()
    {
        freopen("tree.in","r",stdin);
        freopen("tree.out","w",stdout);
        n=read();
        if(n<=100)
        {
            using namespace _20;
            m=read();x=read();
            for(int i=1;i<=m;i++)
            {
                for(int f=1;f<=n;f++)
                    fa[f][i]=fa[f][i-1];
                op=(read()+lastans*x)%3;
                if(op==0)
                {
                    tx=(read()+lastans*x)%n+1;ty=(read()+lastans*x)%n+1;
                    fa[tx][i]=ty;
                }
                else if(op==1)
                {
                    t=(read()+lastans*x)%m;u=(read()+lastans*x)%n+1;k=(read()+lastans*x)%n;
                    while(fa[u][t]&&k)
                    {
                        u=fa[u][t];
                        k--;
                    }
                    if(k!=0)
                        lastans=0;
                    else 
                        lastans=u;
                    write(lastans);
                }
                else
                {
                    t=(read()+lastans*x)%m;u=(read()+lastans*x)%n+1;
                    k=0;
                    while(fa[u][t])
                    {
                        k++;
                        u=fa[u][t];
                    }
                    lastans=k;
                    write(k);
                }
            }
            return 0;
        }
        else 
        {
            using namespace _30;
            m=read();t=read();
            for(int i=1;i<=m;i++)
            {
                o[i].op=read()%3;
                if(o[i].op==0)
                {
                    tx=read()%n+1;
                    ty=read()%n+1;
                    fa[tx][0]=ty;
                    maxx[tx][0]=i;
                }
                else if(o[i].op==1) 
                {
                    o[i].t=read()%m;
                    o[i].u=read()%n+1;
                    o[i].k=read()%n;
                }
                else 
                {
                    o[i].t=read()%m;
                    o[i].u=read()%n+1;
                }
            }        
            for(t=1;t<=20;t++)
            {
                for(int i=1;i<=n;i++)
                {
                    fa[i][t]=fa[fa[i][t-1]][t-1];
                    maxx[i][t]=max(maxx[i][t-1],maxx[fa[i][t-1]][t-1]);
                }
            }
            for(int i=1;i<=m;i++)
            {
                hear:
                if(o[i].op==1)
                {
                    t=o[i].t;
                    u=o[i].u;
                    k=o[i].k;
                    if(k==0)
                    {
                        write(u);
                        continue;
                    }
                    for(int f=20;f>=0;f--)
                    {
                        if(k>=(1<<f))
                        {
                            if(maxx[u][f]>t)
                            {
                                write(0);
                                i++;
                                if(i<=m)
                                    goto hear;
                                else 
                                    return 0;
                            }
                            u=fa[u][f];
                            k-=(1<<f);
                        }
                    }
                    write(u);
                }
                else if(o[i].op==2)
                {
                    t=o[i].t;
                    u=o[i].u;
                    k=0;
                    for(int f=20;f>=0;f--)
                    {
                        if(maxx[u][f]<=t&&fa[u][f])
                        {
                            u=fa[u][f];
                            k+=(1<<f);
                        }
                    }
                    write(k);
                }
            }
            return 0;
        }
    }
    50分美滋滋

      

  • 相关阅读:
    8张图带你轻松温习 Java 知识.md
    关于 Java 序列化你不知道的 5 件事
    为什么 String 是不可变的?
    如何使用 Nginx 优雅地限流?
    JAVA泛型编程笔记
    java_接口的应用
    java_抽象类应用
    深入理解Java的接口和抽象类
    java_重写与重载的区别
    Java:按值传递还是按引用传递详细解说
  • 原文地址:https://www.cnblogs.com/qywyt/p/10497154.html
Copyright © 2011-2022 走看看