Description

有一棵n个点的结构未知的树,初始时只有1号点是已被访问的。

你可以调用交互库的询问函数explore(x,y),其中x是已访问的点,y是任意点。

它会返回x向y方向走第一步的点,如果该点未被访问,则将其标记为已访问。

你需要实现一个函数,它通过接口得到n和T,需要在T次explore操作内将所有的点标记(也就是说走完这棵树)。

要求最严格的两档数据:

n<=300000,T<=300020,且原树为一条链(1号点不一定是端点)。

n<=300000,T<=5000000

Solution

显然我们要将链的情况分开讨论

考虑这样一个做法,我们将编号随机排列,每次找到排列中第一个尚未被访问的点,从当前所在的链端开始explore,若走到的点是未访问的说明这个点就在这一侧,直接一直扩展到目标点。否则说明这个点在链的另一侧,跳到链的另一端一直扩展到目标点。

这样的出错(即链两边跳)的期望次数是\(\log n\)的

大概是因为每次期望都会消掉某一条链的一半这样。

考虑一棵树怎么做。

我们用一个LCT来维护已经扩展出来的树,将1作为根,每一次访问从1开始,在当前所在的prefer链上二分然后explore,若扩展出的点是未访问点则一直怼下去,否则就修改二分区间(实际上在splay上走),如果不在同一条prefer链上就跳到那一条去。

每次找到目标点就access

注意这里需要尽量保持splay的平衡,每次搞出新点都access一下。

具体可以看代码(有些地方可能比较谜,改一点就差很远)

均摊次数就是\(O(n\log n)\)的

Code

#include <bits/stdc++.h>
#include "rts.h"
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 300005
using namespace std; int cnt;
bool bz[N];
namespace LCT
{
int sz[N],r[N],f[N],fn[N],dep[N],t[N][2],li[N],ri[N];
void up(int k)
{
sz[k]=sz[t[k][0]]+sz[t[k][1]]+1;
li[k]=(t[k][0])?li[t[k][0]]:k;
ri[k]=(t[k][1])?ri[t[k][1]]:k;
}
void hb(int p,int x,int y)
{
if(x&&p>=0) t[x][p]=y;
if(y) fn[y]=p,f[y]=x;
}
void rot(int k)
{
int fa=f[k],p=fn[k];
hb(p,fa,t[k][1-p]);
hb(fn[fa],f[fa],k);
hb(1-p,k,fa);
up(fa),up(k);
}
int d[N];
void splay(int k,int x)
{
while(f[k]!=x&&fn[k]!=-1&&f[k]!=0)
{
if(f[f[k]]==x||fn[f[k]]==-1||f[f[k]]==0) rot(k);
else if(fn[k]==fn[f[k]]) rot(f[k]),rot(k);
else rot(k),rot(k);
}
up(k);
}
void access(int k)
{
int r=k;
splay(k,0);
fn[t[k][1]]=-1,t[k][1]=0;
up(k);
while(f[k]!=0)
{
int fa=f[k];
splay(fa,0);
fn[t[fa][1]]=-1,hb(1,fa,k);
up(fa),k=fa;
}
splay(r,0);
}
void link(int x,int y)
{
access(x);f[y]=x,fn[y]=-1,up(y);
}
void fd(int x,int y)
{
splay(x,0);
while(x!=y)
{
cnt++;
int p=explore(x,y);
if(p==ri[t[x][0]]) x=t[x][0];
else if(p==li[t[x][1]]) x=t[x][1];
else
{
if(bz[p]) splay(p,0);
else up(p),link(x,p),bz[p]=1;
x=p;
}
}
access(y);
}
}
using namespace LCT; int de[N];
void solve3(int n,int T)
{
int x=1,y=1;
int i=1;
while(i<=n-1)
{
int w=explore(x,de[i]);
if(bz[w]) swap(x,y),w=explore(x,de[i]),cnt++;
bz[w]=1;
while(w!=de[i]) w=explore(w,de[i]),bz[w]=1,cnt++;
x=w;
while(i<=n-1&&bz[de[i]]) i++;
}
} void play(int n, int T, int dataType)
{
memset(bz,0,sizeof(bz));
bz[1]=sz[1]=dep[1]=1;
up(1);
fo(i,2,n) de[i-1]=i,sz[i]=1;
random_shuffle(de+1,de+n);
if(dataType==3) {solve3(n,T);return;}
int i=1,w=1;
while(i<=n-1)
{
fd(1,de[i]);
while(i<=n-1&&bz[de[i]]) i++;
}
n++,n--;
}

[LibreOJ #2341]【WC2018】即时战略【交互】【LCT】的更多相关文章

  1. [WC2018]即时战略(LCT,splay上二分)

    [UOJ题面]http://uoj.ac/problem/349 一道非常好的与数据结构有关的交互题. 首先先看部分分做法, 一上来我们肯定得钦定一个 \(explore\) 的顺序,直接随机就好. ...

  2. [WC2018]即时战略——动态点分治(替罪羊式点分树)

    题目链接: [WC2018]即时战略 题目大意:给一棵结构未知的树,初始时除1号点其他点都是黑色,1号点是白色,每次你可以询问一条起点为白色终点任意的路径,交互库会自动返回给你这条路径上与起点相邻的节 ...

  3. 「WC2018即时战略」

    「WC2018即时战略」 题目描述 小 M 在玩一个即时战略 (Real Time Strategy) 游戏.不同于大多数同类游戏,这个游戏的地图是树形的.也就是说,地图可以用一个由 \(n\) 个结 ...

  4. WC2018 即时战略

    交互题 一棵树,一开始只有 1 号点是已知的,其他的都是未知的,你可以调用函数 explore(x,y) ,其中 x 必须是已知的,函数会找到 x 到 y 路径上第二个点,并把它标成已知,求最小步数使 ...

  5. 【UOJ#349】[WC2018] 即时战略

    题目链接 题意 一开始已知一号点. 每次可以选定一个已知点和一个未知点,然后交互库会返回从已知点出发到达未知点路径上的第二个点. 要求在有限步之内知道每一个点. 次数要求: 链的情况要求 \(O(n) ...

  6. loj2341「WC2018」即时战略(随机化,LCT/动态点分治)

    loj2341「WC2018」即时战略(随机化,LCT/动态点分治) loj Luogu 题解时间 对于 $ datatype = 3 $ 的数据,explore操作次数只有 $ n+log n $ ...

  7. 【WC2018】即时战略

    题目描述 小M在玩一个即时战略(Real Time Strategy)游戏.不同于大多数同类游戏,这个游戏的地图是树形的. 也就是说,地图可以用一个由 n个结点,n?1条边构成的连通图来表示.这些结点 ...

  8. 【WC2018】即时战略(动态点分治,替罪羊树)

    [WC2018]即时战略(动态点分治,替罪羊树) 题面 UOJ 题解 其实这题我也不知道应该怎么确定他到底用了啥.只是想法很类似就写上了QwQ. 首先链的部分都告诉你要特殊处理那就没有办法只能特殊处理 ...

  9. 「WC2018」即时战略

    「WC2018」即时战略 考虑对于一条链:直接随便找点,然后不断问即可. 对于一个二叉树,树高logn,直接随便找点,然后不断问即可. 正解: 先随便找到一个点,问出到1的路径 然后找别的点,考虑问出 ...

  10. 【Unity3D】使用鼠标键盘控制Camera视角(即时战略类游戏视角):缩近,拉远,旋转

    今天写一个demo,要用到鼠标键盘控制三维视角,因此写了个脚本用于控制. 该脚本可以用于即时战略类游戏的视角,提供了缩进,拉伸,旋转.同时按住鼠标右键不放,移动鼠标可以实现第一人称视角的效果. usi ...

随机推荐

  1. Hbase 系列(一)基本概念

    Hbase 系列(一)基本概念 HBase 是 Apache 旗下一个高可靠性.高性能.面向列.可伸缩的分布式存储系统.利用 HBase 技术可在廉价 PC 服务器上搭建起大规模的存储化集群.使用 H ...

  2. android4.2 高用zing拍照后,返回其它页面操作时,主线程关掉或程序退出的问题解决

    产生错误的代码: @Override protected void onCreate(Bundle savedInstanceState) { StrictMode.setThreadPolicy(n ...

  3. 一起做RGB-D SLAM(7) (完结篇)

    第七讲 添加回环检测 2016.11 更新 把原文的SIFT替换成了ORB,这样你可以在没有nonfree模块下使用本程序了. 回环检测的阈值作出了相应的调整. 请以现在的github上源码为准. 简 ...

  4. Linux gcc支持的语法 __attribute__ 属性设置

    __attribute__实际上是gcc专有的一种语法,是用来设置函数属性.变量属性.类属性的 语法:之前在C中的结构体对齐中提到过,当时是用来告诉编译器这个结构体的对齐方式 ,其实他还有很多种用法, ...

  5. python int函数转换浮点型字符串的坑???

    python中的int函数可以将数字或字符串转换为整型数字类型,具体功能就不提了 最近发现一个问题,对于字符串'1.1'之类的,int转换的时候会报异常,这是为什么,个人感觉直接转换成1不就行了,干嘛 ...

  6. c+内存管理机制

    内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的 检查代码和对C++的痛恨,但内存管理在C++中无处不在,内存 ...

  7. DE0-Nano-SoC开发板诡异的电源电路方案设计分析

    这些日子一直在设计自己的Cyclone V SoC开发板,由于我们这种散兵游勇,是断然没有厂家和代理技术支持的,因此只能找各种现成方案参考.其实Cyclone V SoC芯片的外围电路设计不难,无非就 ...

  8. linux下的文本操作之 文本查找——grep

    摘要:你有没有这样的应用场景:调试一个程序,出现debug的提示信息,现在你需要定位是哪个文件包含了这个debug信息,也就是说,你需要在一个目录下的多个文件(可能包含子目录)中查找某个字符串的位置: ...

  9. PHP 实现简单搜索功能

    方案:问答搜索 1. 搜索结果列表,高亮显示搜索关键词内容 2. 用户输入内容,点击搜索        2.1 获取用户的搜索内容:        2.2 调用分词服务,获取对搜索内容的分词:     ...

  10. Blend 2015 教程 (五) 自定义状态

    本篇再补充一块内容,就是自定义状态的介绍. 自定义状态用于封装用户控件在各种状态之间切换时的外观变化及其动画效果,方便调用.比如有个用户控件用于实现类似舞台幕布打开和关闭切换的效果,可以创建幕布关闭和 ...