離線可持久化動態樹

  不,你想多了,我並沒有發明.  


  動態樹?我會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分美滋滋

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章