zoukankan      html  css  js  c++  java
  • 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);
            }
        }
    }
    View Code
  • 相关阅读:
    css3360度旋转动画
    PAT 1084 外观数列(20)(代码+思路+推荐测试用例)
    PAT 1083 是否存在相等的差(20)(代码+思路)
    PAT 1082 射击比赛(20)(代码+思路)
    PAT 1079 延迟的回文数(代码+思路)
    PAT 1078 字符串压缩与解压(20)(代码+思路)
    PAT 1077 互评成绩计算(20)(代码+思路)
    PAT 1073 多选题常见计分法(20)(代码+思路)
    PAT 1072 开学寄语(20)(代码+思路)
    PAT 1069 微博转发抽奖(20)(代码+思路+测试点4)
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10359042.html
Copyright © 2011-2022 走看看