#Trie#AGC044 C - Strange Dance

题意

3n 个人在绕圈圈跳舞。我们从任意一个人开始,给这些人环绕标号,记为 0,1,,3n1

现在有两种舞 :

  • Salasa 舞。所有人走向其对应的位置,位于位置 i 的人走向第 j 个位置当且仅当 i,j 的三进制表示,1 对应 22 对应 1。比如,(46)10=(1201)3 可以走向 (65)10=(2102)3,当然 65 也走向 46
  • Rumba 舞。所有人走向其所在位置编号加 1 的位置。如果等于 3n1,去 0

现在给你一个 T 序列表示以上两种舞。请问最后每个人站在哪里?


分析

从低位到高位建 Trie,维护 w[p] 表示位置为根结点到结点 p 的路径所表示的三进制数的是第几个人。

处理 S 也就是实现交换 trie[p][1]trie[p][2],需要实现懒标记进行延迟交换。

处理 T 也就是全局加一,三进制就是让 trie[p][(z+1)mod3]=trie[p][z]

时间复杂度 O(3n+n|T|)


代码

#include <iostream>
#include <string>
using namespace std;
const int N = 800011;
string T;
int rt, n, len, tot, three[21], trie[N][3], w[N], lazy[N], ans[N];
void build(int &rt, int dep, int now) {// 建 Trie
    if (!rt)
        rt = ++tot;
    if (dep == n) {
        w[rt] = now;
        return;
    }
    for (int i = 0; i < 3; ++i)
        build(trie[rt][i], dep + 1, now + i * three[dep]);
}
void plusone(int rt) {// 全局加一
    if (!trie[rt][0])
        return;
    if (lazy[rt]) {// 延迟标记
        for (int i = 0; i < 3; ++i)
            lazy[trie[rt][i]] ^= 1;
        swap(trie[rt][1], trie[rt][2]);
        lazy[rt] = 0;
    }
    int t = trie[rt][0];
    trie[rt][0] = trie[rt][2];
    trie[rt][2] = trie[rt][1];
    trie[rt][1] = t;
    plusone(trie[rt][0]);
}
void dfs(int rt, int dep, int now) {
    if (dep == n) {
        ans[w[rt]] = now;
        return;
    }
    if (lazy[rt]) {
        for (int i = 0; i < 3; ++i)
            lazy[trie[rt][i]] ^= 1;
        swap(trie[rt][1], trie[rt][2]);
        lazy[rt] = 0;
    }
    for (int i = 0; i < 3; ++i)
        dfs(trie[rt][i], dep + 1, now + i * three[dep]);
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n >> T, len = T.length();
    three[0] = 1;
    for (int i = 1; i <= n; ++i)
        three[i] = three[i - 1] * 3;
    build(rt, 0, 0);
    for (int i = 0; i < len; ++i)
        if (T[i] == 'S')
            lazy[rt] ^= 1;
        else
            plusone(rt);
    dfs(rt, 0, 0);
    for (int i = 0; i < three[n]; ++i)
        cout << ans[i] << ' ';
    return 0;
}
posted @   lemondinosaur  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
历史上的今天:
2020-02-09 #网络流,树状数组#JZOJ 4020 Revolution with JZOJ 4018 Magic
2020-02-09 #高精度,排列组合、dp#JZOJ 2755 树的计数
2020-02-09 #三分,分治,计算几何,prim#JZOJ 3860 地壳运动
2020-02-09 #dp、树状数组#JZOJ 3859 孤独一生
2020-02-09 #搜索,计算几何#JZOJ 4016 圈地为王
2020-02-09 #费马小定理#JZOJ 4015 数列
点击右上角即可分享
微信分享提示