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 }