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);                 
			}   
		}
	}
}

  

posted @ 2020-05-22 12:48  EM-LGH  阅读(192)  评论(0编辑  收藏  举报