UOJ #349. 【WC2018】即時戰略

Description

Solution

鏈的情況是 \(O(n+log)\) 的,要分開討論
由於鏈的情況已知的點一定是一段連續的,維護兩個端點不斷往兩邊擴展即可

樹的情況是 \(O(n*log)\)
要支持快速查找到一個點所在的位置,我們可以用點分治做一下,找到這個點屬於哪一個兒子所在的塊,遞歸找下去就可以了
由於需要存一個兒子所在的塊,需要用到 \(map\) ,複雜度是 \(O(n*log^2)\) 的,並且要定期重構.
另一種是用 \(LCT\) , \(access\) 均攤複雜度的做法
兩種做法操作次數是 \(O(n*log)\)

#include "rts.h"
#include<bits/stdc++.h>
using namespace std;
const int N=300010;
int id[N],ch[N][2],fa[N],L[N],R[N];bool vis[N];
inline bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline void upd(int x){
    L[x]=R[x]=x;
    if(ch[x][0])L[x]=L[ch[x][0]];
    if(ch[x][1])R[x]=R[ch[x][1]];
}
inline void rotate(int x){
    int y=fa[x];bool t=ch[y][1]==x;
    ch[y][t]=ch[x][!t];fa[ch[y][t]]=y;
    ch[x][!t]=y;fa[x]=fa[y];
    if(!isrt(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
    fa[y]=x;upd(y);upd(x);
}
inline void splay(int x){
    while(!isrt(x)){
        int y=fa[x],p=fa[y];
        if(isrt(y))rotate(x);
        else if((ch[p][0]==y)==(ch[y][0]==x))rotate(y),rotate(x);
        else rotate(x),rotate(x);
    }
}
inline void access(int x){
    int y=0;
    while(x)splay(x),ch[x][1]=y,upd(x),x=fa[y=x];
}
inline int getroot(int x){while(!isrt(x))x=fa[x];return x;}
inline void ins(int x){
    int s=getroot(1),t;
    while(!vis[x]){
        t=explore(s,x);
        if(t==L[ch[s][1]])s=ch[s][1];
        else if(t==R[ch[s][0]])s=ch[s][0];
        else if(vis[t])s=getroot(t);
        else fa[t]=s,vis[s=t]=1;
    }
    access(x);
}
void play(int n, int T, int dataType){
    srand(time(NULL));
    for(int i=2;i<=n;i++)id[i]=i;
    for(int i=1;i<=5;i++)random_shuffle(id+2,id+n+1);
    if(dataType==3){
        int l=1,r=explore(1,id[2]);
        vis[r]=1;
        for(int i=2;i<=n;i++){
            int x=id[i];
            if(vis[x])continue;
            int t=explore(l,x);
            if(vis[t]){while(r!=x)vis[r=explore(r,x)]=1;}
            else{
                vis[t]=1;
                while(l!=x)vis[l=explore(l,x)]=1;
            }
        }
        return ;
    }
    for(int i=1;i<=n;i++)L[i]=R[i]=i;
    for(int i=2;i<=n;i++)if(!vis[id[i]])ins(id[i]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章