WC2018 即时战略

交互题

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

对于 30% 的数据,是一条链,操作次数 $O(n+logn)$

剩下的数据,操作次数 $O(nlogn)$

$n \leq 300000$

sol:

先吐槽 loj 的交互题评测机制

把 ac 时应该输出的东西输出,然后就 a 了

不 shing 话

链的情况想了半天,题解是 xjb 暴力,服

因为这个 explore 的性质,当前已知的一定是一条线段

维护一下当前已知的左端点和右端点,每次随机一个未知的点蹦过去,如果走错方向了就换个方向走

这样出错次数期望 log ? 不知道

树的情况很好想

首先想到一个很朴素的暴力,对于每个点,从根 explore 下去

然后会发现自己多 explore 了很多已知的点,当需要 explore 一个点的时候你只需要跳到他那个子树上,从那个点开始 explore 就可以了

现在就是要维护一棵树滋磁

1.加入一个点

2.快速跳到一个点

动态点分治/LCT 都可以

但谁都知道 LCT 好写吧...于是果断 LCT

每次操作后 access 保证复杂度即可

至于为什么 access?道理相当于 splay 每次把查询点旋到根保证复杂度?

什么?uoj 有 hack 数据?random_shuffle 一下就可以了

跑到了 rk#3 应该是比较欧的原因

因为之后再也跑不了那么快了

#include <bits/stdc++.h>
#include "rts.h"
#define LL long long
#define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
#define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
using namespace std;
inline int read() {
    int x = 0, f = 1; char ch;
    for (ch = getchar(); !isdigit(ch); ch = getchar()) if (ch == ‘-‘) f = -f;
    for (; isdigit(ch); ch = getchar()) x = 10 * x + ch - ‘0‘;
    return x * f;
}
const int maxn = 300010;
#define ls ch[x][0]
#define rs ch[x][1]
int vis[maxn], pid[maxn];
int fa[maxn], ch[maxn][2], mn[maxn], mx[maxn];
inline int isroot(int x) { return ((ch[fa[x]][0] != x) && (ch[fa[x]][1] != x)); }
inline void pushup(int x) {
    mn[x] = mx[x] = x;
    if (ls) mn[x] = mn[ls];
    if (rs) mx[x] = mx[rs];
}
inline void rotate(int x) {
    int y = fa[x], z = fa[y];
    int l = (ch[y][1] == x), r = l ^ 1;
    if (!isroot(y)) ch[z][ch[z][1] == y] = x;
    fa[x] = z; fa[ch[x][r]] = y; fa[y] = x;
    ch[y][l] = ch[x][r]; ch[x][r] = y;
    pushup(y); pushup(x);
}
inline void splay(int x) {
    while (!isroot(x)) {
        int y = fa[x], z = fa[y];
        if (!isroot(y)) {
            if (ch[z][0] == y ^ ch[y][0] == x) rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
    pushup(x);
}
void access(int x) {
    for (int y = 0; x; y = x, x = fa[x]) {
        splay(x);
        rs = y;
        pushup(x);
    }
}
inline int findroot(int x) {
    while (!isroot(x)) x = fa[x];
    return x;
}
void play(int n, int T, int dataType) {
//    srand((unsigned long long)new char);
    for (int i = 2; i <= n; i++) pid[i] = i;
    random_shuffle(pid + 2, pid + n + 1);
    if (dataType == 3)  // chain
    {
        vis[1] = 1;
        int l = 1, r = 1;
        for (int i = 2; i <= n; i++) {
            int x = pid[i], now;
            if (vis[x]) continue;
            if (!vis[now = explore(l, x)]) {
                while (now != x) vis[now] = 1, now = explore(now, x);
                vis[x] = 1;
                l = x;
            } else {
                now = explore(r, x);
                while (now != x) vis[now] = 1, now = explore(now, x);
                vis[x] = 1;
                r = x;
            }
        }
    } else {
        vis[1] = 1;
        mn[1] = mx[1] = 1;
        for (int i = 2; i <= n; i++) {
            if (vis[pid[i]]) continue;
            int now = pid[i], x = findroot(1), ret;
            while (!vis[now]) {
                ret = explore(x, now);
                if (mn[rs] == ret) x = rs;
                else if (mx[ls] == ret) x = ls;
                else if (vis[ret]) x = findroot(ret);
                else vis[ret] = 1, mn[ret] = mx[ret] = ret, fa[ret] = x, x = ret;
            }
            access(now);
        }
    }
}

原文地址:https://www.cnblogs.com/Kong-Ruo/p/10359042.html

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

WC2018 即时战略的相关文章

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

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

【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#349 【WC2018】即时战略

题目链接 正解:$link-cut \ tree$. 这道题我在考场上从看题到放弃只花了$20$多分钟.. 爆刚$t2$无果,$12$点的钟声响起,我无奈地开始看这道题,然后发现了生的希望.. 只写了二十几分钟,然后又滚回去刚$t2$了..正解根本就没去想了(虽然本来也不会.. 不得不说这道题的标算还是很妙的,我就算去想也不可能往$LCT$这方面想.. 我们每次新开一个点,就直接从根结点开始$explore$. 我们可以用$LCT$维护当前这棵树的链,于是每次从现在$splay$的根结点开始往下

【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

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

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

刘沐真:游戏化十大元素

把游戏中的智慧和法则,运用在现实世界,这就是游戏化.正确的游戏化运用,可以使孩子从玩家转变成学霸,让新兴的创始人,具备别人看不透的核心竞争力,让玩游戏的人,娱乐的同时,其他维度也变得更强... 目前市面上的游戏化书籍,基本都是学院派理论,实操性非常差,莫风老师向你保证,只要你掌握以下游戏化十大元素,你对游戏化的运用将超过任何一个“专家” 1.核心玩法 理解了核心玩法,你的游戏化之路就成功了一半. 一款游戏好不好玩,成败往往就是核心玩法.在游戏世界,仙剑的核心玩法就是45度角战斗,超级玛丽就是跳跃

各种机械键盘轴的区别,到底什么轴好

http://www.pcviva.com/jixiejianpanshenmezhouhao.html 如果你已经清楚什么是机械键盘,也阅读了<机械键盘什么牌子好>这篇文章,你可能要挑的,就是机械键盘的轴了.机械键盘什么轴好呢,我们先看下机械键盘的白轴.黑轴.青轴.茶轴.红轴的区别.  (在多数情况下,PC万岁所说“机械键盘轴”都指Cherry MX轴.) 机械键盘轴的区别(概览) 机械键盘轴的区别: 白轴操作压力克数比黑轴大段落感比茶轴强已停产 黑轴操作压力:58.9g±14.7g没有段落