uoj#349 【WC2018】即时战略

题目链接

正解:$link-cut \ tree$。

这道题我在考场上从看题到放弃只花了$20$多分钟。。

爆刚$t2$无果,$12$点的钟声响起,我无奈地开始看这道题,然后发现了生的希望。。

只写了二十几分钟,然后又滚回去刚$t2$了。。正解根本就没去想了(虽然本来也不会。。

不得不说这道题的标算还是很妙的,我就算去想也不可能往$LCT$这方面想。。

我们每次新开一个点,就直接从根结点开始$explore$。

我们可以用$LCT$维护当前这棵树的链,于是每次从现在$splay$的根结点开始往下走。

如果$explore$返回的点在左子树,我们就往左移,在右子树则往右移,如果不在这棵树我们就直接跳到$explore$返回的这个点所在的树。

可以发现,在一棵$splay$上我们最多只会移动$splay$深度次数,那么时间复杂度和查询复杂度也可以保证在$O(n log n)$。

注意一点,就是每次找到目标点以后都要通过$access$来保证复杂度,以及链的情况需要特判。

  1 // RTS sample program
  2 #include <bits/stdc++.h>
  3 #include "rts.h"
  4 #define il inline
  5 #define RG register
  6 #define N (300005)
  7
  8 using namespace std;
  9
 10 int ch[N][2],fa[N],l[N],r[N],p[N],vis[N],lst,nxt,n;
 11
 12 deque<int> Q;
 13 deque<int>::iterator it;
 14
 15 il void work(){
 16   Q.push_back(p[1]);
 17   for (RG int i=2,x,v,op;i<=n;++i){
 18     if (vis[p[i]]) continue;
 19     v=explore(p[1],p[i]);
 20     if (nxt==v){
 21       op=2,it=Q.end(),x=*(--it);
 22       while (1){
 23     v=explore(x,p[i]),vis[v]=1;
 24     op==1?Q.push_front(v):Q.push_back(v);
 25     if (v==p[i]) break; x=v;
 26       }
 27     } else if (lst==v){
 28       op=1,it=Q.begin(),x=*it;
 29       while (1){
 30     v=explore(x,p[i]),vis[v]=1;
 31     op==1?Q.push_front(v):Q.push_back(v);
 32     if (v==p[i]) break; x=v;
 33       }
 34     } else{
 35       if (!lst) op=1,lst=v; else op=2,nxt=v;
 36       op==1?Q.push_front(v):Q.push_back(v);
 37       vis[v]=1; if (v==p[i]) continue; x=v;
 38       while (1){
 39     v=explore(x,p[i]),vis[v]=1;
 40     op==1?Q.push_front(v):Q.push_back(v);
 41     if (v==p[i]) break; x=v;
 42       }
 43     }
 44   }
 45   return;
 46 }
 47
 48 il int isroot(RG int x){
 49   return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
 50 }
 51
 52 il void pushup(RG int x){
 53   l[x]=ch[x][0]?l[ch[x][0]]:x;
 54   r[x]=ch[x][1]?r[ch[x][1]]:x; return;
 55 }
 56
 57 il void rotate(RG int x){
 58   RG int y=fa[x],z=fa[y],k=ch[y][0]==x;
 59   if (!isroot(y)) ch[z][ch[z][1]==y]=x;
 60   fa[x]=z,ch[y][k^1]=ch[x][k],fa[ch[x][k]]=y;
 61   ch[x][k]=y,fa[y]=x,pushup(y),pushup(x); return;
 62 }
 63
 64 il void splay(RG int x){
 65   while (!isroot(x)){
 66     RG int y=fa[x],z=fa[y];
 67     if (!isroot(y)) rotate((ch[z][0]==y)^(ch[y][0]==x)?x:y);
 68     rotate(x);
 69   }
 70   return;
 71 }
 72
 73 il void access(RG int x){
 74   RG int t=0;
 75   while (x){
 76     splay(x),ch[x][1]=t;
 77     pushup(x),t=x,x=fa[x];
 78   }
 79   return;
 80 }
 81
 82 void play(int _n, int T, int dataType) {
 83   srand(19260817+3),n=_n;
 84   for (RG int i=1;i<=n;++i) p[i]=i;
 85   random_shuffle(p+2,p+n+1);
 86   if (dataType==3){ work(); return; }
 87   for (RG int i=1;i<=n;++i) l[i]=r[i]=i;
 88   for (RG int i=2,x,v;i<=n;++i){
 89     if (vis[p[i]]) continue; x=p[1];
 90     while (x!=p[i]){
 91       splay(x);
 92       while (1){
 93     v=explore(x,p[i]);
 94     if (v==r[ch[x][0]]) x=ch[x][0];
 95     else if (v==l[ch[x][1]]) x=ch[x][1];
 96     else{
 97       if (!vis[v]) vis[v]=1,fa[v]=x;
 98       x=v; break;
 99     }
100       }
101     }
102     access(x);
103   }
104   return;
105 }

原文地址:https://www.cnblogs.com/wfj2048/p/8443128.html

时间: 2024-08-30 11:41:56

uoj#349 【WC2018】即时战略的相关文章

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

题目链接: [WC2018]即时战略 题目大意:给一棵结构未知的树,初始时除1号点其他点都是黑色,1号点是白色,每次你可以询问一条起点为白色终点任意的路径,交互库会自动返回给你这条路径上与起点相邻的节点并且如果这个点为黑色则将它变为白色,要求在不多于给定次数的询问内使所有点变为白色. 大致思路为按一定顺序分别将n-1个点变为白点,为了防止被卡,需要对2~n的序列随机打乱再按打乱后的顺序逐个变白. 数据范围分为三种,分开讲解(假设当前要变白的点为x): 一.完全二叉树 这一部分比较简单,我们只需要

WC2018 即时战略

交互题 一棵树,一开始只有 1 号点是已知的,其他的都是未知的,你可以调用函数 explore(x,y) ,其中 x 必须是已知的,函数会找到 x 到 y 路径上第二个点,并把它标成已知,求最小步数使整棵树都已知 对于 30% 的数据,是一条链,操作次数 $O(n+logn)$ 剩下的数据,操作次数 $O(nlogn)$ $n \leq 300000$ sol: 先吐槽 loj 的交互题评测机制 把 ac 时应该输出的东西输出,然后就 a 了 不 shing 话 链的情况想了半天,题解是 xjb

【WC2018】即时战略

题目描述 小M在玩一个即时战略(Real Time Strategy)游戏.不同于大多数同类游戏,这个游戏的地图是树形的. 也就是说,地图可以用一个由 n个结点,n?1条边构成的连通图来表示.这些结点被编号为 1 ~ n. 每个结点有两种可能的状态:"已知的"或"未知的".游戏开始时,只有 1号结点是已知的.在游戏的过程中,小M可以尝试探索更多的结点.具体来说,小M每次操作时需要选择一个已知的结点 x,和一个不同于 x 的任意结点 y(结点 y 可以是未知的). 然

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

今天写一个demo,要用到鼠标键盘控制三维视角,因此写了个脚本用于控制. 该脚本可以用于即时战略类游戏的视角,提供了缩进,拉伸,旋转.同时按住鼠标右键不放,移动鼠标可以实现第一人称视角的效果. 1 using UnityEngine; 2 using System.Collections; 3 4 public class CameraController : MonoBehaviour { 5 6 7 public float near = 20.0f; 8 public float far

[UOJ#348][WC2018]州区划分

[UOJ#348][WC2018]州区划分 试题描述 小 \(S\) 现在拥有 \(n\) 座城市,第ii座城市的人口为 \(w_i\),城市与城市之间可能有双向道路相连. 现在小 \(S\) 要将这 \(n\) 座城市划分成若干个州,每个州由至少一个城市组成,每个城市在恰好一个州内. 假设小 \(S\) 将这些城市划分成了 \(k\) 个州,设 \(V_i\) 是第 \(i\) 个州包含的所有城市组成的集合. 定义一条道路是一个州的内部道路,当且仅当这条道路的两个端点城市都在这个州内. 如果一

【UOJ349】【WC2018】即时战略 LCT 动态点分治

这是一道交互题 题目大意 有一棵\(n\)个点的树.最开始\(1\)号点是白的,其他点是黑的. 每次你可以执行一个操作:\(explore(x,y)\).要求\(x\)是一个白点.该函数会返回从\(x\)到\(y\)的路径上第二个点的坐标并把该点染白. 要求你把所有点都染成白色. 设操作次数为\(t\). 对于\(30\%\)的数据:这棵树是一条链(不保证\(1\)在链的一端),\(n=300000,t=O(n+\log n)\) 对于另外\(70\%\)的数据:\(n=300000,t=O(n

即时战略游戏编队

不打字了,直接贴图片吧!我只想说,这sb的题目,你把输入描写清楚好不,到底输不输入n啊,元素顺序是怎么样的啊,真扯淡,最后只过了40%,我都不知道怎么过的.输入顺序都是我自己瞎蒙的. 你看他的输入,还用什么大括号括起来,到底是什么意思. 分析:简单的dp,有限背包问题.先计算所有数的总和,然后除以2,记为s,然后计算和为s的组合方式都多少种,符合题目描述的判重方式. 1 /* 2 ID: y1197771 3 PROG: test 4 LANG: C++ 5 */ 6 #include<bits

游戏编程精粹系列书籍目录一览

游戏编程精粹1 第1章 通用编程技术 1.0 神奇的数据驱动设计(Steve Rabin) 3 1.0.1 点子1--基础 3 1.0.2 点子2--最低标准 3 1.0.3 点子3--杜绝硬编码 3 1.0.4 点子4--将控制流写成脚本 4 1.0.5 点子5--什么时候不适合使用脚本? 5 1.0.6 点子6--避免重复数据 5 1.0.7 点子7--开发工具来生成数据 6 1.0.8 结论 6 1.1 面向对象的编程与设计技术(James Boer) 7 1.1.1 代码风格 7 1.1

Vijos P1066 弱弱的战壕【多解,线段树,暴力,树状数组】

弱弱的战壕 描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒[email protected][email protected]). 但是,战壕有一个弱点,就是只能攻击它的左下方,说白了就是横纵坐标都不大于它的点(mx:“我的战壕为什么这么菜”ToT).这样,永恒就可以从别的地方进攻摧毁战壕,从而消灭mx的部队. 战壕都有一个保护范围,同它的攻击