题目链接

题意

一开始已知一号点。

每次可以选定一个已知点和一个未知点,然后交互库会返回从已知点出发到达未知点路径上的第二个点。

要求在有限步之内知道每一个点。

次数要求:

链的情况要求 \(O(n)\)

其余是 \(O(nlogn)\)

Sol

首先是链的情况,记录当前左右端点不断往后探索即可。

然后是树,初始想法肯定就是不断迭代,最坏情况是 \(O(n^2)\) 的。

我们的瓶颈在于如果树的深度比较大,我们迭代的时候来回走了很多个圈就不好处理。

那么我们很容易想到用点分树来优化我们迭代的过程。

于是动态维护点分树即可。

每次新加一个点的时候直接加入,向上更新点分树祖先的 \(size\) ,设定一个平衡因子,当当前子树大小过大时就把当前子树暴力重构一下。记录每一个点在点分树中的深度就很好做了。

code:

  1. #include<bits/stdc++.h>
  2. #include "rts.h"
  3. using namespace std;
  4. const int N=3e5+10;
  5. namespace TP3{
  6. int n;int lnow,rnow;bool del[N];int S[N];
  7. void work(int _n){
  8. n=_n;
  9. lnow=rnow=1;for(int i=1;i<n;++i) S[i]=i+1;del[1]=1;
  10. srand(time(NULL));random_shuffle(S+1,S+n);
  11. for(int i=1;i<n;++i){
  12. int now=lnow;bool f=0;
  13. while(!del[S[i]]) {
  14. int v=explore(now,S[i]);
  15. if(del[v]) now=rnow,f=1;
  16. else {
  17. del[v]=1;now=v;
  18. if(f==0) lnow=now;
  19. else rnow=now;
  20. }
  21. }
  22. if(rand()&1) swap(lnow,rnow);
  23. }
  24. return;
  25. }
  26. }
  27. namespace Sol{
  28. int n;
  29. typedef double db;
  30. const db alpha=0.7;
  31. struct edge{int to,next;}a[N<<1];
  32. int head[N],cnt=0;
  33. inline void add(int x,int y){a[++cnt]=(edge){y,head[x]};head[x]=cnt;}
  34. int fa[N],vis[N],size[N],f[N],que[N],had[N],mark[N],sz[N],dep[N];
  35. int rt;int now,SZ,RT,UP;
  36. void Find(int u,int fr){
  37. sz[u]=1,f[u]=0;
  38. for(int v,i=head[u];i;i=a[i].next){
  39. v=a[i].to;if(v==fr||vis[v]) continue;
  40. Find(v,u);sz[u]+=sz[v];
  41. f[u]=max(f[u],sz[v]);
  42. }
  43. f[u]=max(f[u],SZ-sz[u]);
  44. if(!RT||(f[u]<f[RT])) RT=u;
  45. }
  46. void Build(int u,int fr){
  47. fa[u]=fr;size[u]=1;dep[u]=dep[fr]+1;vis[u]=1;
  48. for(int v,i=head[u];i;i=a[i].next){
  49. v=a[i].to;if(dep[v]<UP||vis[v]) continue;
  50. RT=0;SZ=sz[v];Find(v,u);
  51. int To=RT;Build(To,u);
  52. size[u]+=size[To];
  53. }
  54. return;
  55. }
  56. void Clear(int u,int fa){
  57. vis[u]=0,mark[u]=0;
  58. for(int v,i=head[u];i;i=a[i].next){v=a[i].to;if(v==fa||dep[v]<UP) continue;Clear(v,u);}
  59. return;
  60. }
  61. inline void Rebuild(int u){// 重构子树
  62. SZ=size[u];UP=dep[u];RT=0;
  63. Clear(u,0);Find(u,0);if(rt==u) rt=RT;
  64. Build(RT,fa[u]);
  65. return;
  66. }
  67. void Maintain(int u){// 向上更新点分树 size 并判断重构
  68. if(!fa[u]) {if(mark[u]) Rebuild(u);return;}
  69. ++size[fa[u]];
  70. if(size[fa[u]]*alpha<size[u]) mark[fa[u]]=1;
  71. Maintain(fa[u]);
  72. if(mark[u]) Rebuild(u);// 找到最上面需要重构的点
  73. return;
  74. }
  75. void work(int _n){
  76. n=_n;
  77. for(int i=1;i<n;++i) que[i]=i+1;
  78. srand(time(NULL));
  79. random_shuffle(que+1,que+n);
  80. had[1]=size[1]=vis[1]=rt=1,dep[1]=1;
  81. int tot=1;
  82. for(int i=1;i<n;++i) {
  83. now=rt;
  84. while(!had[que[i]]){
  85. int p=explore(now,que[i]);
  86. if(had[p]) {
  87. while(now!=fa[p]) p=fa[p];now=p;
  88. }
  89. else {
  90. ++tot;had[p]=1;
  91. add(now,p),add(p,now);
  92. fa[p]=now,size[p]=1,vis[p]=1,dep[p]=dep[now]+1;
  93. Maintain(p);now=p;
  94. }
  95. }
  96. }
  97. }
  98. }
  99. void play(int n, int T, int dataType) {
  100. if(dataType==3) TP3::work(n);
  101. else Sol::work(n);
  102. }

【UOJ#349】[WC2018] 即时战略的更多相关文章

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

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

  2. 「WC2018即时战略」

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

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

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

  4. WC2018 即时战略

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

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

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

  6. 【WC2018】即时战略

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

  7. 「WC2018」即时战略

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

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

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

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

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

随机推荐

  1. The file is inaccessible to Server.

    ArcGIS Unable to Start serviceserver安装后,启动服务失败,报错信息如下:Unable to Start service. Error (Server object  ...

  2. JS中设置cookie,读取cookie,删除cookie

    在开发时,碰到一个需求,需要保存一个表的信息(非隐私),希望下次打开还存在.于是想到用cookie,一番折腾完成.示例数据都是假的,打马赛克是怕泄密. 这个表取名为Data,为Array,每一行是一个 ...

  3. 中国MOOC_零基础学Java语言_第5周 数组

    第5周 数组 5.1 数组 5.2 数组计算 public class Main { public static void main(String[] args) { for (int i = 1; ...

  4. iframe根据子frame的高度自动高度

    <script type="text/javascript"> //光标移动到顶部 this.to_top=function(){ $("html,body& ...

  5. 正则表达式断言(Assertions)

    一 零宽正向先行断言 x(?=y) 仅匹配被y跟随的x. const regExp = /Jack(?=Sparrow|Dawson)/g; const str = 'JackJones JackSp ...

  6. C++ Primer笔记(1)——连续读取数据、类型对应的尺寸、类型转换、字符串分行写法

    这次要看看C++ Primer,这本基本上就是必读书籍了.下面的内容就是一些之前没有学过的知识的笔记. 读取数量不定的输入数据 虽然很简单,但是还是记一下: #include <iostream ...

  7. java中的命名规则

    转载自:http://growstep.diandian.com/post/2011-08-17/3989094 1.类名首字母应该大写.属性(成员变量).方法.对象变量以及所有标识符(如形式参数.实 ...

  8. 书籍:wpf学习书籍介绍

    WPF参考书推荐 下面先整理下,本人主要学习的WPF参考书: 1.WPF编程宝典(C#2010) 该书:(必读) 心得体会:读完该书后,你对WPF的基础和基本控件的使用,包括WPF的编程模型,相比Wi ...

  9. 索引之----mysql联合索引

    重要概念: 1.对于mysql来说,一条sql中,一个表无论其蕴含的索引有多少,但是有且只用一条. 2.对于多列索引来说(a,b,c)其相当于3个索引(a),(a,b),(a,b,c)3个索引,又由于 ...

  10. SparkStreaming DStream转换

    1.无状态转换操作 (1)无状态转化操作就是把简单的RDD转化操作应用到每个批次上,也就是转换DStream中的每一个RDD. 部分无状态转化操作: (2)尽管这些函数韩起来像作用在整个流上一样,但事 ...