LOJ #2341. 「WC2018」即时战略 交互+LCT+随机化
第一次做交互题,感觉挺有趣的.
对于链的部分,可以随机一个点拓展,直到拓展到该点为止.
但是最坏情况下可能每次都要询问两次(每次左右端点都选错).
据说随机化情况下出错的次数大概为 $O( \log n)$ 次.
对于树的部分最暴力的做法是从根节点开始询问,暴力拓展到叶子.
假设钦定一条从根节点向下延申的链,“拐点” 具有一定的单调性,所以可以在链上二分(即 splay 上二分)
code:
#include "rts.h" #include <bits/stdc++.h> #define N 1000005 #define ll long long #define lson s[x].ch[0] #define rson s[x].ch[1] using namespace std; int vis[N],arr[N],sta[N]; int ran(int l) { return (ll)rand()*rand()%l+1; } struct data { int ch[2],f,rev,l,r; }s[N]; inline int get(int x) { return s[s[x].f].ch[1]==x; } inline int isr(int x) { return s[s[x].f].ch[0]!=x&&s[s[x].f].ch[1]!=x; } inline void pushup(int x) { s[x].l=s[x].r=x; if(lson) s[x].l=s[lson].l; if(rson) s[x].r=s[rson].r; } inline void mark(int x) { s[x].rev^=1,swap(lson,rson),swap(s[x].l,s[x].r); } inline void push(int x) { if(s[x].rev) { if(lson) mark(lson); if(rson) mark(rson); s[x].rev^=1; } } void rotate(int x) { int old=s[x].f,fold=s[old].f,which=get(x); if(!isr(old)) s[fold].ch[s[fold].ch[1]==old]=x; s[old].ch[which]=s[x].ch[which^1]; if(s[old].ch[which]) s[s[old].ch[which]].f=old; s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold; pushup(old),pushup(x); } void splay(int x) { int v=0,u=x,fa; for(sta[++v]=u;!isr(u);u=s[u].f) sta[++v]=s[u].f; for(;v;--v) push(sta[v]); for(u=s[u].f;(fa=s[x].f)!=u;rotate(x)) if(s[fa].f!=u) rotate(get(fa)==get(x)?fa:x); } void access(int x) { for(int y=0;x;y=x,x=s[x].f) splay(x),rson=y,pushup(x); } void makert(int x) { access(x),splay(x),mark(x); } void link(int x,int y) { s[x].f=y; } int getrt(int x) { while(!isr(x)) x=s[x].f; return x; } void play(int n, int T, int dataType) { srand((unsigned)time(NULL)); if(dataType==3) { int L=1,R=1; for(int i=2;i<=n;++i) arr[i]=i; random_shuffle(arr+2,arr+1+n); for(int i=2;i<=n;++i) { int u=arr[i]; if(vis[u]) continue; int p=explore(L,u); if(!vis[p]) { vis[p]=1,L=p; while(p!=u) p=explore(p,u),L=p,vis[p]=1; } else { int p2=explore(R,u); vis[p2]=1,R=p2; while(p2!=u) p2=explore(p2,u),R=p2,vis[p2]=1; } } } else { vis[1]=1,arr[1]=1; for(int i=2;i<=n;++i) arr[i]=i; random_shuffle(arr+2,arr+1+n); for(int i=2;i<=n;++i) { int u=arr[i]; if(vis[u]) continue; int x=getrt(1),cn=0; while(1) { push(x); int cur=explore(x,u); if(!vis[cur]) { vis[cur]=1,link(cur,x),x=cur; while(cur!=u) { cur=explore(cur,u); vis[cur]=1,link(cur,x),x=cur; } access(x); break; } if(cur==s[rson].l) x=rson; else if(cur==s[lson].r) x=lson; else x=getrt(cur); } } } }