您的位置:首页 > 其它

uoj#349 【WC2018】即时战略

2018-02-11 20:24 295 查看
题目链接

正解:$link-cut \ tree$。

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

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

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

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

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

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

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

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

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

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

// RTS sample program
#include <bits/stdc++.h>
#include "rts.h"
#define il inline
#define RG register
#define N (300005)

using namespace std;

int ch
[2],fa
,l
,r
,p
,vis
,lst,nxt,n;

deque<int> Q;
deque<int>::iterator it;

il void work(){
Q.push_back(p[1]);
for (RG int i=2,x,v,op;i<=n;++i){
if (vis[p[i]]) continue;
v=explore(p[1],p[i]);
if (nxt==v){
op=2,it=Q.end(),x=*(--it);
while (1){
v=explore(x,p[i]),vis[v]=1;
op==1?Q.push_front(v):Q.push_back(v);
if (v==p[i]) break; x=v;
}
} else if (lst==v){
op=1,it=Q.begin(),x=*it;
while (1){
v=explore(x,p[i]),vis[v]=1;
op==1?Q.push_front(v):Q.push_back(v);
if (v==p[i]) break; x=v;
}
} else{
if (!lst) op=1,lst=v; else op=2,nxt=v;
op==1?Q.push_front(v):Q.push_back(v);
vis[v]=1; if (v==p[i]) continue; x=v;
while (1){
v=explore(x,p[i]),vis[v]=1;
op==1?Q.push_front(v):Q.push_back(v);
if (v==p[i]) break; x=v;
}
}
}
return;
}

il int isroot(RG int x){
return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
}

il void pushup(RG int x){
l[x]=ch[x][0]?l[ch[x][0]]:x;
r[x]=ch[x][1]?r[ch[x][1]]:x; return;
}

il void rotate(RG int x){
RG int y=fa[x],z=fa[y],k=ch[y][0]==x;
if (!isroot(y)) ch[z][ch[z][1]==y]=x;
fa[x]=z,ch[y][k^1]=ch[x][k],fa[ch[x][k]]=y;
ch[x][k]=y,fa[y]=x,pushup(y),pushup(x); return;
}

il void splay(RG int x){
while (!isroot(x)){
RG int y=fa[x],z=fa[y];
if (!isroot(y)) rotate((ch[z][0]==y)^(ch[y][0]==x)?x:y);
rotate(x);
}
return;
}

il void access(RG int x){
RG int t=0;
while (x){
splay(x),ch[x][1]=t;
pushup(x),t=x,x=fa[x];
}
return;
}

void play(int _n, int T, int dataType) {
srand(19260817+3),n=_n;
for (RG int i=1;i<=n;++i) p[i]=i;
random_shuffle(p+2,p+n+1);
if (dataType==3){ work(); return; }
for (RG int i=1;i<=n;++i) l[i]=r[i]=i;
for (RG int i=2,x,v;i<=n;++i){
if (vis[p[i]]) continue; x=p[1];
while (x!=p[i]){
splay(x);
while (1){
v=explore(x,p[i]);
if (v==r[ch[x][0]]) x=ch[x][0];
else if (v==l[ch[x][1]]) x=ch[x][1];
else{
if (!vis[v]) vis[v]=1,fa[v]=x;
x=v; break;
}
}
}
access(x);
}
return;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: