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$了,所以我也不知道正解是什么。
正解:$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; }
相关文章推荐
- [WC2018]即时战略
- 【UOJ349】【WC2018】即时战略 LCT 动态点分治
- UOJ #349. 【WC2018】即时战略
- [LCT] WC2018. 即时战略
- UOJ#349:【WC2018】即时战略 (LCT)
- [UOJ349][WC2018]即时战略-Link Cut Tree
- THUWC2018&&WC2018游记
- THUWC2018&WC2018凉凉记
- [WC 2018]州区划分
- bzoj5152 [Wc2018]通道
- WC2018 游记
- bzoj5153 [Wc2018]州区划分
- WC2018 游记
- [FMT] WC2018.州区划分
- WC2018游记
- [WC2018]州区划分
- 【UOJ347】【WC2018】通道 边分治 虚树 DP
- 【WC2018】州区划分
- WC2018 滚粗记
- PKUWC2018 & NOI WC2018 凉凉记