zoukankan      html  css  js  c++  java
  • 【HNOI2010】弹飞绵羊 题解(分块)

    前言:其实这个题是用LCT做的,但蒟蒻因为太弱了,只会分块QAQ。

    -----------------------------

    题目链接

    题目大意:给定$n$个装置,每个装置有弹力系数$k_i$,即在这个位置上会被弹到$i+k_i$。现在有两个操作:1.修改某个弹力装置的弹力系数。2.问从$x$开始,弹几次后所处位置大于$n$。

    预处理在每个点需要被弹飞的次数$sum[i]$和到达的下一个点$out[i]$。然后进行分块。修改的时候只需要在所在块内的$sum$和$out$即可。

    每次询问和修改的时间复杂度都是$O(sqrt n)$。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=200005;
    int out[maxn],sum[maxn],num[maxn];
    int n,m,block,tot;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline int getpos(int x)
    {
        return (x-1)/block+1;
    }
    inline void work(int l,int r)
    {
        for (int i=r;i>=l;i--) 
        {
            if (i+num[i]>getpos(i)*block) sum[i]=1,out[i]=i+num[i];
            else sum[i]=sum[i+num[i]]+1,out[i]=out[i+num[i]];
        }
    }
    int main()
    {
        n=read();block=sqrt(n);
        tot=n/block;if (n%block) tot++;
        for (int i=1;i<=n;i++) num[i]=read();
        work(1,n);
        m=read();
        for (int i=1;i<=m;i++)
        {
            int flag=read(),y=read()+1;
            if (flag==1)
            {
                int ans=sum[y],x=out[y];
                for (int j=getpos(y);j<=tot&&x<=n;j++) ans+=sum[x],x=out[x];
                printf("%d
    ",ans);
            }
            else{
                int z=read();num[y]=z;
                work((getpos(y)-1)*block+1,getpos(y)*block);
            }
        }
        return 0;
    }
  • 相关阅读:
    认识AppDomain类
    认识Math类
    控制输入法
    开发中常见错误
    flash视频窗口被关闭卡住了父窗口
    TransactionScope 事务 net2.0
    发现system.collection 命名空间下面的类大部分是基于数组来存储
    utf8 编码出现空白
    如何WEB上的消息提醒
    当前不会命中断点
  • 原文地址:https://www.cnblogs.com/Invictus-Ocean/p/13293004.html
Copyright © 2011-2022 走看看