• 【bzoj2002】弹飞绵羊(分块)


    题目分析

      题意:每个点都有一个值$v_i$,从一个点出发,每走到一个点,会跳到i+vi的位置,问需要跳多少次能跳出n?带修改。

      此题可以用lct做,此处使用了分块:将序列分块后,每个点记录从此点最少跳几次能跳出当前块,和跳出后到达的位置,倒叙可以优化。

      这样询问时只要一直跳至多$sqrt{n}$个块就能知道答案。

      对于修改操作,只需将修改点和修改点之前的当前块元素重新使用上述处理,同样倒叙可以优化。

    code

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    using namespace std;
    
    const int N = 2e5 + 5;
    int n, m, S;
    int blkCnt, blk[N], bl[500], br[500];
    long long val[N], step[N], des[N];
    
    inline int read(){
        int i = 0, f = 1; char ch = getchar();
        for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
        if(ch == '-') f = -1, ch = getchar();
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            i = (i << 3) + (i << 1) + (ch - '0');
        return i * f;
    }
    
    inline long long readL(){
        long long i = 0, f = 1; char ch = getchar();
        for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
        if(ch == '-') f = -1, ch = getchar();
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            i = (i << 3) + (i << 1) + (ch - '0');
        return i * f;
    }
    
    inline void wr(long long x){
        if(x < 0) putchar('-'), x = -x;
        if(x > 9) wr(x / 10);
        putchar(x % 10 + '0');
    }
    
    inline void init(){
        bl[blkCnt = 1] = 1;
        for(int i = 1; i <= n; i++){
            if(i % S == 0){
                br[blkCnt] = i;
                blk[i] = blkCnt;
                if(i + 1 <= n){
                    bl[++blkCnt] = i + 1;
                    continue;
                }
            }
            blk[i] = blkCnt;
        }
        br[blkCnt] = n;
    }
    
    int main(){
        n = read(), S = sqrt(n);
        for(int i = 1; i <= n; i++) val[i] = readL();
        init();
        for(int i = n; i >= 1; i--){
            int tmp = i;
            bool flag = false;
            step[i] = 0;
            while(tmp + val[tmp] <= br[blk[i]]){
                tmp += val[tmp], step[i]++;
                if(step[tmp]){
                    step[i] += step[tmp], des[i] = des[tmp], flag = true;
                    break;
                }
            }
            if(!flag) des[i] = tmp + val[tmp], step[i]++;
        }
        m = read();
        for(int t = 1; t <= m; t++){
            int opt = read();
            if(opt == 1){
                int src = read() + 1, ans = 0, tmp;
                tmp = src;
                while(des[tmp] <= n) ans += step[tmp], tmp = des[tmp];
                ans += step[tmp];
                wr(ans), putchar('
    ');
            }
            else{
                int pos = read() + 1, value = readL();
                if(val[pos] == value) continue;
                val[pos] = value;
                for(int i = bl[blk[pos]]; i <= pos; i++) step[i] = 0;
                
                for(int i = pos; i >= bl[blk[pos]]; i--){
                    int tmp = i; bool flag = false;
                    while(tmp + val[tmp] <= br[blk[pos]]){
                        tmp += val[tmp], step[i]++;
                        if(step[tmp]){
                            step[i] += step[tmp], des[i] = des[tmp], flag = true;
                            break;
                        }
                    }
                    if(!flag) des[i] = tmp + val[tmp], step[i]++;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    推荐几款Winform下的皮肤控件!
    PetShop之业务逻辑层设计 《解剖PetShop》系列之五
    25款.NET开发必备工具推荐
    在aspx页面实现高亮显示搜过关键字
    PetShop之ASP.NET缓存 《解剖PetShop》系列之四
    ASP.NET页面加载顺序
    PetShop之表示层设计 《解剖PetShop》系列之六
    C#打包应用程序
    .NET获取英文月份缩写名(可获取其他国家)
    SQL Server 日期格式化输出
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7257876.html
Copyright © 2020-2023  润新知