UOJ#349. 【WC2018】即时战略

原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ349.html

题解

被cqz D没了。我D cly 关你啥事(逃

首先链的情况直接rand就好了。

期望次数 $O(n+\log n)$ 。

然而我一开始写挂了。


 

开始扯淡

我用这个模数,就可以过原题数据:

('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')

但是用以下两种都不行:

('G'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')

('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I'+'N'+'O'+'I')

第一个说明叫cly外号会掉rp,因为他是大佬。

第二个说明cly是大佬不屑于AKNOI。


对于树的情况,容易想到的是一个和紫荆花之恋一样的替罪羊树维护点分树的做法。

但是显然GG了。

考虑我们将一个节点连到主体部分这个操作,类似于 LCT 中的 access 。于是我们发现直接写个 LCT 就没了。

写法有多种,但是考虑到常数因子,建议连接完之后一遍access上去。不要自顶向下一边access一边splay一边连边,这样常数大。

代码

#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#include "rts.h"
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
#define outarr(a,L,R) printf(#a"[%d...%d] = ",L,R);\
						For(_v2,L,R)printf("%d ",a[_v2]);puts("");
using namespace std;
typedef long long LL;
const int N=300005;
#define Ask explore
namespace so0{
	int L=1,R=1,rv=0;
	int vis[N];
	vector <int> v;
	void main(int n){
		v.clear();
		For(i,2,n)
			v.pb(i);
		random_shuffle(v.begin(),v.end());
		while (!v.empty()){
			int x=v.back();
			v.pop_back();
			if (vis[x])
				continue;
			int y=Ask(L,x);
			if (y==rv){
				while (R!=x)
					R=Ask(R,x),vis[R]=1;
			}
			else {
				rv=L,L=y,vis[L]=1;
				while (L!=x)
					rv=L,L=Ask(L,x),vis[L]=1;
			}
		}
	}
}
namespace so1{
	int n;
	int vis[N];
	int father[N],hson[N];
	int son[N][2],fa[N];
	vector <int> v;
	#define ls son[x][0]
	#define rs son[x][1]
	bool isroot(int x){
		return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
	}
	int wson(int x){
		return son[fa[x]][1]==x;
	}
	void rotate(int x){
		int y=fa[x],z=fa[y],L=wson(x),R=L^1;
		if (!isroot(y))
			son[z][wson(y)]=x;
		fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
		son[y][L]=son[x][R],son[x][R]=y;
	}
	void splay(int x){
		for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
			if (!isroot(y))
				rotate(wson(x)==wson(y)?y:x);
	}
	void access(int x){
		int t=0;
		while (x){
			splay(x);
			hson[x]=t;
			while (son[hson[x]][0])
				hson[x]=son[hson[x]][0];
			rs=t,t=x,x=fa[x];
		}
	}
	void Ins(int a){
		int x=1,y;
		while (fa[x])
			x=fa[x];
		while (x!=a){
			y=Ask(x,a);
			if (!vis[y])
				break;
			if (y==father[x])
				x=ls;
			else if (y==hson[x])
				x=rs;
			else {
				while (!isroot(y))
					y=fa[y];
				x=y;
			}
		}
		while (1){
			fa[y]=father[y]=x;
			vis[y]=1;
			x=y;
			if (x==a)
				break;
			y=Ask(x,a);
		}
		access(x);
	}
	#undef ls
	#undef rs
	void main(int n){
		so1::n=n;
		v.clear();
		vis[1]=1;
		For(i,2,n)
			v.pb(i);
		random_shuffle(v.begin(),v.end());
		clr(father),clr(hson);
		while (!v.empty()){
			int x=v.back();
			v.pop_back();
			if (!vis[x])
				Ins(x);
		}
	}
}
void play(int n,int T,int type){
	srand(_SEED_);
	if (type==3)
		so0::main(n);
	else
		so1::main(n);
}

  

posted @ 2019-03-15 20:07  zzd233  阅读(334)  评论(0编辑  收藏  举报