[LCT] WC2018. 即时战略

之前询问得到的树用LCT维护,然后每次询问从根开始询问

询问次数和复杂度都是 O(nlogn) O ( n log ⁡ n )

UPD:被HACK了

#include 
#include 
#include 
#include 
#include 
#include "rts.h"

using namespace std;

const int N=300010;

struct node{
  node *ch[2],*f;
  int rev;
}a[N],*root;

inline int isl(node *x){ return !x->f || (x->f->ch[0]!=x && x->f->ch[1]!=x); }
inline int isr(node *x){ return x->f && x->f->ch[1]==x; }

inline void Push(node *x){
  if(!x || !x->rev) return ;
  swap(x->ch[0],x->ch[1]);
  if(x->ch[0])
    x->ch[0]->rev^=1;
  if(x->ch[1])
    x->ch[1]->rev^=1;
  x->rev=0;
}

void Pushtop(node *x){
  if(!isl(x)) Pushtop(x->f); Push(x);
}

inline void rot(node *x){
  node *y=x->f,*z=y->f; int wh=isr(x);
  if(!isl(y)) z->ch[isr(y)]=x; x->f=z;
  if(y->ch[wh]=x->ch[wh^1]) y->ch[wh]->f=y;
  (x->ch[wh^1]=y)->f=x;
}

inline void splay(node *x){
  Pushtop(x);
  for(;!isl(x);rot(x)) if(!isl(x->f)) rot(isr(x->f)^isr(x)?x:x->f);
}

inline void access(node *x){
  for(node *t=0;x;x=x->f)
    splay(x),x->ch[1]=t,t=x;
}

inline void reverse(node *x){
  access(x); splay(x); x->rev^=1;
}

inline void link(int _x,int _y){
  node *x=a+_x,*y=a+_y;
  x->f=y; //access(x);
}

int id[N],vis[N],dpt[N];

inline bool isfa(node *x,node *y){
  if(y==x) return true;
  while(!isl(y)){
    y=y->f;
    if(y==x) return true;
  }
  return false;
}

inline node *Root(node *x){
  while(!isl(x)) x=x->f;
  return x;
}

inline void work(int n){
  vis[1]=1; srand(19260817);
  for(int i=1;i<=n;i++) id[i]=i;
  random_shuffle(id+1,id+1+n);
  int p1=1,p2=1;
  for(int i=1;i<=n;i++){
    int x=id[i];
    if(vis[x]) continue;
    if(rand()&1) swap(p1,p2);
    int c=explore(p1,x);
    if(vis[c]) swap(p1,p2),c=explore(p1,x);
    vis[c]=1; p1=c;
    while(!vis[x]){
      c=explore(p1,x); vis[p1=c]=1;
    }
  }
}

void play(int n,int T,int dataType) {
  if(dataType==3)
    return work(n);
  root=a+1; vis[1]=1;
  for(int i=1;i<=n;i++) id[i]=i;
  random_shuffle(id+1,id+1+n);
  for(int i=1;i<=n;i++){
    int x=id[i];
    if(vis[x]) continue;
    reverse(root);
    node *cur=root;
    while(1){
      Push(cur);
      int c=explore(cur-a,x);
      if(!vis[c]){
    vis[c]=1; dpt[c]=dpt[cur-a]+1; link(c,cur-a); cur=a+c;
    if(c==x) break;
    continue;
      }
      if(isfa(cur,a+c))
    cur=dpt[c]>dpt[cur-a]?cur->ch[1]:cur->ch[0];
      else
    cur=Root(a+c);
    }
    access(cur);
  }
}

你可能感兴趣的:(LCT,交互)