• 【loj2341】【WC2018】即时战略


    题目

    交互题;

    一开始所有点都是黑的,你需要把所有点变白;

    explore(u,v)会将u到v路径上的第二个点变白;

    一开始只有1号点是白色的,你需要让所有点变白;

    对于一条链次数限制(O(n+log n)),普通的树次数限制(O(n log n)) ;

    题解

    • orz yww

    • Part 1

    • 白色区间一定是一条链,记录左右端点;

    • 先假设新点在左边用左端点扩展,如果explore出重复的点,则说明在右边换右端点;

    • 这样一直扩展,最坏(O(2n)),期望(O(n+log n))

    • 浪费次数其实可以看成从头开始的上升子序列的长度,考虑(n)放在哪里:

    • 期望$E_n= 1 + sum_{i=0}^{n-1} frac{1}{n} E_{i} -> E_n = E_{n-1}+frac{1}{n} $  

    • 那么有两边就乘二,再随机一下每次默认的方向就乘二分之一还是log的;

    • Part 2

    • 只需要找到已知树上的离新点最近的点;

    • 可以用在LCT上跳,均摊(n log n),也可以在动态点分树上跳,严格(n log n)

    • 我只会写LCT,LCT需要维护链顶和链底标号;

    • (不知道该如何描述.....建议看看rk1的代码)

      #include<bits/stdc++.h>
      #include "rts.h"
      #define il inline 
      using namespace std;
      const int N=300010;
      int vis[N],p[N],fa[N],ch[N][2],rev[N],L[N],R[N];
      il bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}//
      il bool isch(int x,int y){return ch[x][0]==y||ch[x][1]==y;}//
      il int findrt(int x){while(!isrt(x))x=fa[x];return x;}//
      il void mfy(int x){
      	swap(ch[x][0],ch[x][1]);
      	swap(L[x],R[x]);
      	rev[x]^=1;
      }//
      il void pushdown(int x){
      	if(rev[x]){
      		if(ch[x][0])mfy(ch[x][0]);
      		if(ch[x][1])mfy(ch[x][1]);
      		rev[x]^=1;
      	}
      }
      il void pushup(int x){
      	L[x]=R[x]=x;
      	if(ch[x][0])L[x]=L[ch[x][0]];
      	if(ch[x][1])R[x]=R[ch[x][1]];	
      }//
      il void rotate(int x){
      	int y=fa[x],z=fa[y];
      	if(!isrt(y))ch[z][ch[z][1]==y]=x;
      	int l=ch[y][1]==x,r=l^1;
      	fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
      	ch[y][l]=ch[x][r];ch[x][r]=y;
      	pushup(y);pushup(x);
      }//
      void push(int x){
      	static int sta[N],top;
      	while(!isrt(x))sta[++top]=x,x=fa[x];
      	sta[++top]=x;
      	while(top)pushdown(sta[top--]);
      }//
      il void splay(int x){
      	push(x);
      	for(int y,z;!isrt(x);rotate(x)){
      		y=fa[x],z=fa[y];
      		if(!isrt(y))rotate( (ch[y][0]==x)^(ch[z][0]==y) ? x : y );
      	}
      }//
      il void access(int x){
      	for(int y=0;x;y=x,x=fa[x]){
      		splay(x);
      		ch[x][1]=y;
      		pushup(x);
      	}
      }//
      il void mkrt(int x){access(x);splay(x);mfy(x);}//
      il void link(int x,int y){fa[y]=x;}//
      il void solve(int n){
      	int a[2]={1,1};
      	for(int i=2;i<=n;++i){
      		int u=p[i];if(vis[u])continue;
      		int x=rand()%2,v=explore(a[x],u);
      		if(vis[v])x^=1,v=explore(a[x],u);
      		vis[v]=1;while(v!=u)vis[v=explore(v,u)]=1;
      		a[x]=u;
      	}
      }//
      void play(int n,int T,int typ){
      	srand(23333323);
      	for(int i=1;i<=n;++i)p[i]=i;
      	random_shuffle(p+2,p+n+1);
      	if(typ==3){solve(n);return;}
      	vis[1]=1;
      	for(int i=1;i<=n;++i)L[i]=R[i]=i;
      	for(int i=2,lst=1;i<=n;++i){
      		int u=p[i],v;
      		lst=findrt(1);
      		if(vis[u])continue;
      		while(lst!=u){
      			v=explore(lst,u);
      			pushdown(lst);
      			if(!vis[v])vis[v]=1,link(lst,v),lst=v;
      			else if(v==R[ch[lst][0]])lst=ch[lst][0];
      			else if(v==L[ch[lst][1]])lst=ch[lst][1];
      			else lst=findrt(v);
      		}
      		//mkrt(lst); mkrt会被卡操作常数
      		access(lst);
      	}
      	return ;
      }//
      
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    详解以太坊世界状态
    VDF 不是工作量证明
    以太坊:Go-Ethereum: 编译运行
    【转】理解分布式账本技术: 经济学视角
    Counterfactual 项目:广义的以太坊状态通道
    Solidity 安全:已知攻击方法和常见防御模式综合列表
    Verge 攻击解析
    以太坊区块链的轻客户端
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10827067.html
Copyright © 2020-2023  润新知