OVSolitario-io

导航

倍增&ST算法

倍增

倍增:预处理的就是每个点走 2^i 步的结果
通过预处理go[][]数组,拼凑出需要走的操作数

点击查看代码
#include <bits/stdc++.h>
using namespace std;

const int N = 10;        // 节点数
const int LOG = 20;      // log2(N) 的上界,保证够大

int go[N][LOG];          // go[x][i] 表示从 x 出发走 2^i 步到哪里

int main() {
    int n = 6; // 节点数
    // 初始化 go[x][0] (走 1 步) 
    // 链: 1->2->3->4->5->6->0 (0 表示 null/不存在)
    go[1][0] = 2;
    go[2][0] = 3;
    go[3][0] = 4;
    go[4][0] = 5;
    go[5][0] = 6;
    go[6][0] = 0; // null
    
    // 预处理倍增表
    for (int j = 1; j < LOG; j++) {//20*n
        for (int x = 1; x <= n; x++) {
            int mid = go[x][j-1]; 
            if (mid) go[x][j] = go[mid][j-1]; // 跳 2^(j-1) + 2^(j-1)
            else go[x][j] = 0;
        }
    }
    
    // 示例查询:从 1 出发走 5 步到哪里
    int start = 2, k = 3;
    int cur = start;
    for (int j = 0; j < LOG; j++) {
        if (k & (1 << j)) { // 如果 k 的二进制有第 j 位
            cur = go[cur][j];
            if (!cur) break; // 提前终止
        }
    }
    cout << "从 " << start << " 出发走 " << k << " 步,到达 " << cur << endl;
    return 0;
}
P4155
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 4e5 + 1;
int n, m;
struct Node {
    int id, L, R;
    bool operator< (const Node b) const {
        return L < b.L;
    }
};
Node w[N * 2];
int n2, go[N][20];
void init() {
    int nxt = 1;
    for(int i = 1; i <= n2; ++ i) {
        while(nxt <= n2 && w[nxt].L <= w[i].R) ++ nxt;
        go[i][0] = nxt - 1;
    }
    for(int i = 1; (1 << i) <= n; ++ i) {
        for(int s = 1; s <= n2; ++ s) {
            go[s][i] = go[go[s][i - 1]][i - 1];
        }
    }
}
int res[N];
void getans(int x) {
    int len = w[x].L + m, cur = x, ans = 1;
    for(int i = log2(N); i >= 0; -- i) {
        int pos = go[cur][i];
        if(pos && w[pos].R < len) {
            ans += 1 << i;
            cur = pos;
        }
    }
    res[w[x].id] = ans + 1;
}
int main() {
    cin >> n >> m;
    for(int i = 1; i <= n; ++ i) {
        w[i].id = i;
        cin >> w[i].L >> w[i].R;
        if(w[i].R < w[i].L) {
            w[i].R += m;
        }
    }
    sort(w + 1, w + 1 + n);
    n2 = n;
    for(int i = 1; i <= n; ++ i) {
        ++ n2;
        w[n2] = w[i];
        w[n2].L = w[i].L + m;
        w[n2].R = w[i].R + m;
    }
    init();
    for(int i = 1; i <= n; ++ i) getans(i);
    for(int i = 1; i <= n; ++ i) cout << res[i] << ' ';
    return 0;
}

posted on 2025-10-02 14:30  TBeauty  阅读(5)  评论(0)    收藏  举报