zoukankan      html  css  js  c++  java
  • uoj349【WC2018】即时战略

    题目链接
    WC出了点意外滚粗了,来补补题。
    (O(n^2))的时间复杂度,(O(nlogn))的询问次数应该还是比较好想的,每次要打通到x的路径,对当前已知的树不断的找重心并询问在重心的哪颗子树中走过去。注意到有加点的操作,用紫荆花之恋的那种做法可以做到(O(nlog^2n)),但我不会写...听wys讲课说可以用LCT,想了一下发现挺简单的就去用LCT写了这题。反正就是把1作为根,每次要打通到x的路径时,就可以从1开始,类似二分的过程在每棵splay中不断询问当前点再往其中一棵子树走过去,若得到了一个不在当前splay中的点就需要跳到下一棵splay,找到了目标点就access一下,时间复杂度和询问次数都是(O(nlogn))的,所以链部分的数据要特判一下。

    #include "rts.h"
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define P puts("lala")
    #define cp cerr<<"lala"<<endl
    #define fi first
    #define se second
    #define ln putchar('
    ')
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    
    const int N=300050;
    int p[N],fa[N],ch[N][2],L[N],R[N];
    bool know[N];
    
    inline bool ge(int x) {return ch[fa[x]][1]==x;}
    inline bool isroot(int x) {return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    inline void up(int x)
    {
    	L[x]=x; R[x]=x;
    	if(ch[x][0]) L[x]=L[ch[x][0]];
    	if(ch[x][1]) R[x]=R[ch[x][1]];
    }
    inline void rotate(int x)
    {
    	int f=fa[x],g=fa[f],wh=ge(x);
    	if(!isroot(f)) ch[g][ch[g][1]==f]=x;
    	ch[f][wh]=ch[x][wh^1]; fa[ch[f][wh]]=f;
    	ch[x][wh^1]=f; fa[f]=x;
    	fa[x]=g;
    	up(f); up(x);
    }
    int stk[N],top=0;
    void splay(int x)
    {
    	top=0; stk[++top]=x;
    	for(int i=x;!isroot(i);i=fa[i]) stk[++top]=fa[i];
    	while(top) pushdown(stk[top--]);
    	for(int f;(f=fa[x])&&!isroot(x);rotate(x))
    		if(!isroot(f)) rotate(ge(x)==ge(f)?f:x);
    }
    void access(int x)
    {
    	for(int t=0;x;t=x,x=fa[x])
    		splay(x),ch[x][1]=t,up(x);
    }
    
    
    void play(int n, int T, int opt)
    {
    	for(int i=1;i<=n;++i) p[i]=i;
    	random_shuffle(p+1,p+1+n);
    	know[1]=1;
    	if(opt==3)
    	{
    		int l=1,r=1;
    		for(int i=1;i<=n;++i) if(!know[p[i]])
    		{
    			int x=l,y=explore(x,p[i]);
    			bool rig=0;
    			if(know[y]) x=r,rig=1;
    			else know[y]=1,x=y,rig=0,l=x;
    			while(x!=p[i]) 
    			{
    				x=explore(x,p[i]),know[x]=1;
    				if(rig) r=x;
    				else l=x;
    			}
    		}
    	}
    	else
    	{
    		for(int i=1;i<=n;++i) L[i]=R[i]=i;
    		for(int i=1;i<=n;++i) if(!know[p[i]])
    		{
    			int x=1;
    			while(1)
    			{
    				splay(x);
    				while(1)
    				{
    					int o=explore(x,p[i]);
    					if(o==R[ch[x][0]]) x=ch[x][0];
    					else if(o==L[ch[x][1]]) x=ch[x][1];
    					else
    					{
    						if(!know[o]) know[o]=1,fa[o]=x;
    						x=o; break;
    					}
    				}
    				if(x==p[i]) break;
    			}
    			access(x);
    		}
    	}
    }
    
  • 相关阅读:
    JAVA常用知识总结(十一)——数据库(一)
    JAVA常用知识总结(十)——Maven
    JAVA常用知识总结(九)——线程
    JAVA常用知识总结(八)——计算机网络
    JAVA常用知识总结(七)——Spring
    Spring Cloud Alibaba教程:Nacos
    OpenCV入门(2)- Java第一个程序
    OpenCV入门(1)- 简介
    Elastic Job入门(1)
    Elastic Job入门(3)
  • 原文地址:https://www.cnblogs.com/thkkk/p/8440475.html
Copyright © 2011-2022 走看看