• 魔术帽游戏 [倍增_隐 III]



    Solutionmathcal{Solution}

    建图过程:

    交换操作 可以看作魔术球在 帽子序列 中的 移动,
    使用每个魔术帽的 位置 为 编号 建图,
    操作序列中的 a,ba, b 连两条 有向边, 分别为 aa -> bbaa <- bb, 边权 为当前 操作序号

    带有小球的帽子交换一次, 表示小球走过一条边,
    设该边 编号ii, 到达了 kk 点, 则小球的下一次移动必定会经过满足以下条件的边

    1. kk 相连的
    2. 边的 权值 大于 ii 的 所有边 中 最小的那一条

    对第二个条件的解释: 操作顺序在 ii 后, 继 ii 后 下一次 直接 改变小球的 位置 的操作 所代表的边.

    对于加速该操作, 可以使用如代码中所示 Fk1[i,0]=nxt[i  1]Fk_1[i, 0]=nxt[i 异或 1], 然而这样会导致不可预料的 bugbug (如最下方代码), 所以要谨慎使用

    于是在一个固定的操作序列中, 即固定的中, 小球的起点边一旦确定, 其路径也会随之固定,
    确认了这一点之后, 使用倍增加速

    1. 从魔术球所在的帽子所 连出 的边中寻找 ll 操作
    2. 魔术球从 llrr 的移动

    Codemathcal{Code}

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 2000005;
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    struct Edge{ int nxt, to, w; } edge[maxn << 1];
    
    int N;
    int M;
    int Q;
    int num0;
    int a[maxn];
    int b[maxn];
    int head[maxn];
    int Fk_1[maxn][20];
    int Fk_2[maxn][20];
    
    void Add(int from, int to, int w){
            edge[++ num0] = (Edge){ head[from], to, w };
            head[from] = num0;
    }
    
    int main(){
            freopen("magic.in", "r", stdin);
            freopen("magic.out", "w", stdout);
            N = read();
            M = read();
            Q = read();
            for(reg int i = 1; i <= M; i ++) a[i] = read(), b[i] = read();
            num0 = 1, edge[0].w = 0x7f7f7f7f;
            for(reg int i = M; i >= 1; i --) Add(a[i], b[i], i), Add(b[i], a[i], i);
            for(reg int i = 2; i <= num0; i ++){
                    Fk_1[i][0] = edge[i^1].nxt;
                    Fk_2[i][0] = edge[i].nxt;
            } 
            for(reg int j = 1; j <= 19; j ++)
                    for(reg int i = 2; i <= num0; i ++){
                            Fk_1[i][j] = Fk_1[Fk_1[i][j-1]][j-1]; 
                            Fk_2[i][j] = Fk_2[Fk_2[i][j-1]][j-1];
                    }
            for(reg int i = 1; i <= Q; i ++){
                    int x = read();
                    int l = read();
                    int r = read();
                    int t = head[x];
                    for(reg int i = 19; i >= 0; i --)
                            if(edge[Fk_2[t][i]].w < l) t = Fk_2[t][i];
                    if(edge[t].w < l) t = Fk_2[t][0];
                    t = edge[t].w>r?0:t;
                    for(reg int i = 19; i >= 0; i --)
                            if(edge[Fk_1[t][i]].w <= r) t = Fk_1[t][i];
                    printf("%d
    ", edge[t].to?edge[t].to:x);
            }
            return 0;
    }
    
    

    Code with bugmathcal{Code with bug}

    为什么以 00 为第一条边就 WAWA 掉了…

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 2000005;
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    struct Edge{ int nxt, to, w; } edge[maxn << 1];
    
    int N;
    int M;
    int Q;
    int num0;
    int a[maxn];
    int b[maxn];
    int head[maxn];
    int Fk_1[maxn][22];
    int Fk_2[maxn][22];
    
    void Add(int from, int to, int w){
            edge[num0] = (Edge){ head[from], to, w };
            head[from] = num0 ++;
    }
    
    int main(){
            freopen("magic.in", "r", stdin);
            freopen("magic.out", "w", stdout);
            N = read();
            M = read();
            Q = read();
            for(reg int i = 1; i <= M; i ++) a[i] = read(), b[i] = read();
            memset(head, -1, sizeof head);
            for(reg int i = M; i >= 1; i --) Add(a[i], b[i], i), Add(b[i], a[i], i);
            for(reg int i = 0; i < num0; i ++){
                    Fk_1[i][0] = edge[i^1].nxt;
                    Fk_2[i][0] = edge[i].nxt;
            } 
            for(reg int j = 1; j <= 20; j ++)
                    for(reg int i = 0; i <= num0; i ++){
                            Fk_1[i][j] = Fk_1[Fk_1[i][j-1]][j-1]; 
                            Fk_2[i][j] = Fk_2[Fk_2[i][j-1]][j-1];
                    }
            for(reg int i = 1; i <= Q; i ++){
                    int x = read();
                    int l = read();
                    int r = read();
                    int t = head[x];
    
                    if(t == -1){ printf("%d
    ", x); continue ; }
    
                    for(reg int i = 20; i >= 0; i --){
                            if(Fk_2[t][i] == -1) continue ;
                            if(edge[Fk_2[t][i]].w < l) t = Fk_2[t][i];
                    }
    
                    if(edge[t].w < l) t = Fk_2[t][0];
    
                    if(t == -1 || edge[t].w > r){ printf("%d
    ", x); continue ; }
    
                    for(reg int i = 20; i >= 0; i --){
                            if(Fk_1[t][i] == -1) continue ;
                            if(edge[Fk_1[t][i]].w <= r) t = Fk_1[t][i];
                    }
    
                    printf("%d
    ", edge[t].to?edge[t].to:x);
    
            }
            return 0;
    }
    
    
  • 相关阅读:
    discuz_ucenter_api_for_java的中文问题
    java的编码问题详解
    java的泛型的技巧
    向maven中央仓库提交jar
    Java并发之FutureTask
    java并发之Semaphore
    centos中JDK版本冲突的问题
    C++中嵌入Python
    boost::python的使用
    c++调用python引号的问题
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822630.html
Copyright © 2020-2023  润新知