uoj#349 【WC2018】即时战略

题目链接

 

正解:$link-cut \ tree$。

这道题我在考场上从看题到放弃只花了$20$多分钟。。

爆刚$t2$无果,$12$点的钟声响起,我无奈地开始看这道题,然后发现了生的希望。。

只写了二十几分钟,然后又滚回去刚$t2$了。。正解根本就没去想了(虽然本来也不会。。

不得不说这道题的标算还是很妙的,我就算去想也不可能往$LCT$这方面想。。

我们每次新开一个点,就直接从根结点开始$explore$。

我们可以用$LCT$维护当前这棵树的链,于是每次从现在$splay$的根结点开始往下走。

如果$explore$返回的点在左子树,我们就往左移,在右子树则往右移,如果不在这棵树我们就直接跳到$explore$返回的这个点所在的树。

可以发现,在一棵$splay$上我们最多只会移动$splay$深度次数,那么时间复杂度和查询复杂度也可以保证在$O(n log n)$。

注意一点,就是每次找到目标点以后都要通过$access$来保证复杂度,以及链的情况需要特判。

 

$upd$:这个做法被$hack$了,所以我也不知道正解是什么。

 

  1 // RTS sample program
  2 #include <bits/stdc++.h>
  3 #include "rts.h"
  4 #define il inline
  5 #define RG register
  6 #define N (300005)
  7 
  8 using namespace std;
  9 
 10 int ch[N][2],fa[N],l[N],r[N],p[N],vis[N],lst,nxt,n;
 11 
 12 deque<int> Q;
 13 deque<int>::iterator it;
 14 
 15 il void work(){
 16   Q.push_back(p[1]);
 17   for (RG int i=2,x,v,op;i<=n;++i){
 18     if (vis[p[i]]) continue;
 19     v=explore(p[1],p[i]);
 20     if (nxt==v){
 21       op=2,it=Q.end(),x=*(--it);
 22       while (1){
 23     v=explore(x,p[i]),vis[v]=1;
 24     op==1?Q.push_front(v):Q.push_back(v);
 25     if (v==p[i]) break; x=v;
 26       }
 27     } else if (lst==v){
 28       op=1,it=Q.begin(),x=*it;
 29       while (1){
 30     v=explore(x,p[i]),vis[v]=1;
 31     op==1?Q.push_front(v):Q.push_back(v);
 32     if (v==p[i]) break; x=v;
 33       }
 34     } else{
 35       if (!lst) op=1,lst=v; else op=2,nxt=v;
 36       op==1?Q.push_front(v):Q.push_back(v);
 37       vis[v]=1; if (v==p[i]) continue; x=v;
 38       while (1){
 39     v=explore(x,p[i]),vis[v]=1;
 40     op==1?Q.push_front(v):Q.push_back(v);
 41     if (v==p[i]) break; x=v;
 42       }
 43     }
 44   }
 45   return;
 46 }
 47 
 48 il int isroot(RG int x){
 49   return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
 50 }
 51 
 52 il void pushup(RG int x){
 53   l[x]=ch[x][0]?l[ch[x][0]]:x;
 54   r[x]=ch[x][1]?r[ch[x][1]]:x; return;
 55 }
 56 
 57 il void rotate(RG int x){
 58   RG int y=fa[x],z=fa[y],k=ch[y][0]==x;
 59   if (!isroot(y)) ch[z][ch[z][1]==y]=x;
 60   fa[x]=z,ch[y][k^1]=ch[x][k],fa[ch[x][k]]=y;
 61   ch[x][k]=y,fa[y]=x,pushup(y),pushup(x); return;
 62 }
 63 
 64 il void splay(RG int x){
 65   while (!isroot(x)){
 66     RG int y=fa[x],z=fa[y];
 67     if (!isroot(y)) rotate((ch[z][0]==y)^(ch[y][0]==x)?x:y);
 68     rotate(x);
 69   }
 70   return;
 71 }
 72 
 73 il void access(RG int x){
 74   RG int t=0;
 75   while (x){
 76     splay(x),ch[x][1]=t;
 77     pushup(x),t=x,x=fa[x];
 78   }
 79   return;
 80 }
 81 
 82 void play(int _n, int T, int dataType) {
 83   srand(19260817+3),n=_n;
 84   for (RG int i=1;i<=n;++i) p[i]=i;
 85   random_shuffle(p+2,p+n+1);
 86   if (dataType==3){ work(); return; }
 87   for (RG int i=1;i<=n;++i) l[i]=r[i]=i;
 88   for (RG int i=2,x,v;i<=n;++i){
 89     if (vis[p[i]]) continue; x=p[1];
 90     while (x!=p[i]){
 91       splay(x);
 92       while (1){
 93     v=explore(x,p[i]);
 94     if (v==r[ch[x][0]]) x=ch[x][0];
 95     else if (v==l[ch[x][1]]) x=ch[x][1];
 96     else{
 97       if (!vis[v]) vis[v]=1,fa[v]=x;
 98       x=v; break;
 99     }
100       }
101     }
102     access(x);
103   }
104   return;
105 }

 

posted @ 2018-02-11 20:24  wfj_2048  阅读(487)  评论(0编辑  收藏  举报