zoukankan      html  css  js  c++  java
  • bzoj2002 [Hnoi2010]Bounce 弹飞绵羊——分块

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2002

    第一次用分块,感觉超方便啊;

    如果记录每个点的弹力系数,那么是O(1)修改O(n)查询;

    如果记录每个点几次被弹飞,那么是O(n)修改O(1)查询;

    那么如果分成根号n块,则相当于每块都路径压缩,修改和查询都是根号n的复杂度!

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int const maxn=200005;
    int n,m,k[maxn],nxt[maxn],t[maxn],bh[maxn],K;
    void change(int x)
    {
    //    int s=0,nw=x;
    //    while(bh[nw]==bh[x]&&nw<=n)s++,nw+=k[nw];
    //    t[x]=s;nxt[x]=nw;
        int y=x+k[x];
        if(bh[y]!=bh[x])t[x]=1,nxt[x]=y;
        else t[x]=t[y]+1,nxt[x]=nxt[y];
    }
    int query(int x)
    {
    //    if(x>n)return 0;
    //    int ret=t[x];
    //    ret+=query(nxt[x]);
    //    return ret;
        int ret=0;
        while(x<=n)ret+=t[x],x=nxt[x];
        return ret;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&k[i]);
        K=sqrt(n);
        for(int i=n;i;i--)
        {
    //        if(i>tot*K)tot++;bh[i]=tot;
            bh[i]=(i-1)/K+1;
    //        int j=i,s=0;
    //        while(bh[j]==bh[i]&&j<=n)j+=k[j],s++;
    //        t[i]=s;nxt[i]=j;
            int j=i+k[i];
            if(bh[j]!=bh[i])t[i]=1,nxt[i]=j;
            else t[i]=t[j]+1,nxt[i]=nxt[j];
        }
        scanf("%d",&m);
        int x,y,z;
        while(m--)
        {
            scanf("%d%d",&x,&y);y++;
            if(x==1)printf("%d
    ",query(y));
            else
            {
                scanf("%d",&z);
                k[y]=z;
    //            for(int i=(bh[y]-1)*K+1;i<=y;i++)change(i);
                for(int i=y;i>(bh[y]-1)*K;i--)change(i);
            }
        }
        return 0;
    }
  • 相关阅读:
    每日日报40
    每日日报39
    每日日报38
    vue 0点定时网络请求
    js reduce
    时间选择器 element
    CTF-WEB:PHP 变量
    CTF-WEB:PHP 反序列化
    Java 异常类与捕获异常
    Java 面向对象:内部类
  • 原文地址:https://www.cnblogs.com/Zinn/p/9168200.html
Copyright © 2011-2022 走看看