• BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 分块


    http://www.lydsy.com/JudgeOnline/problem.php?id=2002

    维护cnt[i]表示第i个节点,跳出他所属于的块的最小步数,

    to[i]表示第i个节点,跳出他所属的块的时候,去到那一个位置。

    那么,

    查询:复杂度O(sqrt(n)),不断   ans += cnt[i]   然后   i  = to[i]即可。

    更新:分块这种东西,跟新都是块内更新的,块间都是独立的。

    更新第id个东西,可以知道是不影响后面的。而且如果我知道第id个跳去了那个块,步数也可以算出来的。

    所以只需要修改第id个所在的块,从[L, id]的值即可。因为块间是独立的,

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    const int maxn = 200000 + 20;
    int a[maxn];
    int n;
    int cnt[maxn], to[maxn];
    int magic;
    int calc(int id) {
        return (id - 1) / magic + 1;
    }
    void dfs(int cur, int per) {
        if (cur > n) return;
        if (cnt[cur]) return;
        int t = calc(cur + a[cur]);
        if (t != per) {
            cnt[cur] = 1;
            to[cur] = cur + a[cur];
            dfs(cur + a[cur], t);
        } else {
            dfs(cur + a[cur], per);
            if (cur + a[cur] > n) {
                cnt[cur] = 1;
                to[cur] = n + 1;
            } else {
                cnt[cur] = cnt[cur + a[cur]] + 1;
                to[cur] = to[cur + a[cur]];
            }
        }
    }
    int id;
    int vis[maxn], DFN;
    void update(int cur, int per) {
        if (cur > n) return;
        vis[cur] = DFN;
        int t = calc(a[cur] + cur);
        if (t != per) {
            cnt[cur] = 1;
            to[cur] = a[cur] + cur;
        } else {
            update(cur + a[cur], per);
            if (cur + a[cur] > n) {
                cnt[cur] = 1;
                to[cur] = n + 1;
            } else {
                cnt[cur] = cnt[cur + a[cur]] + 1;
                to[cur] = to[cur + a[cur]];
            }
        }
    }
    void work() {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
        }
        magic = (int)sqrt(n);
        for (int i = 1; i <= n; ++i) {
            if (!cnt[i]) {
                dfs(i, calc(i));
            }
        }
    //    for (int i = 1; i <= n; ++i) {
    //        printf("%d %d
    ", cnt[i], to[i]);
    //    }
        int m;
        scanf("%d", &m);
        while (m--) {
            int op;
            scanf("%d%d", &op, &id);
            ++id;
            if (op == 1) {
                int ans = 0;
                for (int i = id; i <= n; i = to[i]) {
                    ans += cnt[i];
                }
                printf("%d
    ", ans);
            } else {
                int val;
                scanf("%d", &val);
                a[id] = val;
                int t = calc(id);
                ++DFN;
    //            update((t - 1) * magic + 1, t);
                for (int i = (t - 1) * magic + 1; i <= id; ++i) {
                    if (vis[i] == DFN) continue;
                    update(i, t);
                }
            }
        }
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
  • 相关阅读:
    钉钉机器人Golang版本
    Selenium接管已打开的浏览器
    Transformer总结
    机器学习笔记总结
    DSL 和 reactive 噩梦
    简单软件架构的一些好处zz
    使用C#编写ANTLR
    批量编译VB6和VC6工程
    Python数据挖掘银行分控模型的建立
    Linux: grub修复
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7219593.html
Copyright © 2020-2023  润新知