UOJ#349. 【WC2018】即时战略

UOJ#349. 【WC2018】即时战略

http://uoj.ac/problem/349

分析:

  • 对于链的数据,我们瞎随就行,肯定能过去。
  • 否则我们希望用一种不超过\(log\)次询问来找到某个点。
  • 首先还是要随机这个询问序列。
  • 维护点分树,每次询问后一直跳点分树的父亲,用来求出进入了哪棵点分树中子树。
  • 直到这个点未被标记,则插入这个点。
  • 这里我使用替罪羊式重构的方法维护这棵点分树。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include "rts.h"
using namespace std;
#define N 300050
#define pb push_back
#define ep explore
#define AL 0.75
int n,Q[N],S[N],vis[N],cnt,head[N],to[N<<1],nxt[N<<1];
int used[N],tot;
vector<int>v[N];
int tt[N],rt,fa[N],siz[N],fk[N],root,g[N];
void chain() {
	int p=1,q=1,i;
	for(i=1;i<=n;i++) tt[i]=i;
	random_shuffle(tt+2,tt+n+1);
	i=1;
	vis[1]=1;
	while(1) {
		for(;i<=n&&vis[tt[i]];i++) ;
		if(i>n) break;
		int r=ep(p,tt[i]);
		if(vis[r]) {
			r=ep(q,tt[i]);
			q=r; vis[q]=1;
			while(q!=tt[i]) {
				int t=ep(q,tt[i]);
				vis[t]=1; q=t;
			}
		}else {
			p=r; vis[p]=1;
			while(p!=tt[i]) {
				int t=ep(p,tt[i]);
				vis[t]=1; p=t;
			}
		}
		swap(p,q);
	}
}
inline void add(int u,int v) {
	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
void gr(int x,int y) {
	int i; g[x]=1; fk[x]=0;
	for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
		gr(to[i],x); g[x]+=g[to[i]];
		fk[x]=max(fk[x],g[to[i]]);
	}
	fk[x]=max(fk[x],tot-g[x]);
	if(fk[x]<fk[root]) root=x;
}
void gd(int x,int y,int rt) {
	int i;
	siz[rt]++; v[rt].push_back(x);
	for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
		gd(to[i],x,rt);
	}
}
void solve(int x) {
	used[x]=1;
	int i,al=tot;
	v[x].clear();
	siz[x]=0; gd(x,0,x);
	for(i=head[x];i;i=nxt[i]) if(!used[to[i]]) {
		tot=g[to[i]]; if(tot>g[x]) tot=al-g[x];
		root=0; gr(to[i],x); fa[root]=x; solve(root);
	}
}
void insert(int x) {
	int t,koishi=0,i;
	for(t=x;t;t=fa[t]) {
		siz[t]++; v[t].push_back(x);
		if(fa[t]&&siz[t]>siz[fa[t]]*AL) koishi=fa[t];
	}
	if(koishi) {
		int p=koishi,tmp=fa[p];
		int lim=v[p].size();
		for(i=0;i<lim;i++) used[v[p][i]]=0;
		tot=lim;
		root=0;
		gr(p,0);
		fa[root]=tmp;
		if(!tmp) rt=root;
		solve(root);
	}
}
void play(int _n,int _T,int dataType) {
	n=_n;
	if(dataType==3) {
		chain(); return ;
	}
	int i;
	for(i=1;i<=n;i++) tt[i]=i;
	srand(1919810);
	random_shuffle(tt+2,tt+n+1);
	vis[1]=1; rt=1; siz[1]=1; v[1].push_back(1); fk[0]=1<<30;
	for(i=2;i<=n;i++) {
		int x=tt[i],p=rt;
		while(!vis[x]) {
			int q=ep(p,x);
			if(vis[q]) {
				for(;fa[q]!=p;q=fa[q]);
				p=q;
			}else {
				add(p,q); add(q,p);
				fa[q]=p;
				vis[q]=1;
				insert(q);
				p=q;
			}
		}
	}
	return ;
}

posted @ 2019-01-01 21:04  fcwww  阅读(303)  评论(0编辑  收藏  举报