• 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
    ",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);
    }
    

      

  • 相关阅读:
    C/C++优秀书籍清单
    C语言内存管理详解
    C/C++语言常用头文件及函数
    如何学好C++语言
    VS2010 更改MFC标题及标题栏图标和exe图标
    Vue 实现前进刷新,后退不刷新的效果 玩转vue-router里的meta
    $nextTick 页面局部刷新 延迟加载
    吸顶动画 侧边栏 监听滚动条位置 监听元素距离顶部高度
    vue 自定义侧边栏 递归无限子级菜单
    vue element NavMenu 莫名出现蓝色边框
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/UOJ349.html
Copyright © 2020-2023  润新知