zoukankan      html  css  js  c++  java
  • [HNOI2010] 弹飞绵羊 (分块)

    [HNOI2010] 弹飞绵羊

    题目描述

    某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

    输入输出格式

    输入格式:

    第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1。

    接下来一行有n个正整数,依次为那n个装置的初始弹力系数。

    第三行有一个正整数m,

    接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。

    输出格式:

    对于每个i=1的情况,你都要输出一个需要的步数,占一行。

    输入输出样例

    输入样例#1:

    4
    1 2 1 1
    3
    1 1
    2 1 1
    1 1

    输出样例#1:

    2
    3

    说明

    对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

    Solution

    分块...

    对于块中每个点,我们统计它什么时候会弹出块,以及弹出块后会弹到哪里

    对于修改(将v[x]修改为y),我们只需要暴力修改本块内x之前的信息,因为后面的我们不会影响,最坏时间复杂度(O(sqrt n))

    对于查询操作,我们每次都会跳一个块,最坏跳(sqrt n)个,所以最坏时间复杂度也是(O(sqrt n))

    然后就没了...

    Code

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define rg register
    #define lol long long
    #define Min(a,b) (a)<(b)?(a):(b)
    #define Max(a,b) (a)>(b)?(a):(b)
    #define in(i) (i=read())
    using namespace std;
    const int N=2e5+10;
    int read() {
        int ans=0,f=1; char i=getchar();
        while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
        while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0',i=getchar();
        return ans*f;
    }
    int n,m,blo;
    int v[N],pos[N],l[530],r[530],nex[N],sum[N];
    void change(int x,int y) {
        v[x]=y; int AQ=pos[x];
        for(int i=x;i>=l[AQ];i--)
            if(i+v[i]>r[AQ]) sum[i]=1,nex[i]=i+v[i];
            else sum[i]=sum[i+v[i]]+1,nex[i]=nex[i+v[i]];
    }
    
    int query(int x,int ans=0) {
        while(x<=n) {
            ans+=sum[x];
            x=nex[x];
        }return ans;
    }
    int main() {
        in(n); blo=sqrt(n);
        for(int i=1;i<=n;i++) in(v[i]),pos[i]=(i-1)/blo+1;
        for(int i=1;i<=pos[n];i++) {
            l[i]=r[i-1]+1,r[i]=Min(i*blo,n);
            for(int j=r[i];j>=l[i];j--)
                if(j+v[j]>r[i]) sum[j]=1,nex[j]=j+v[j];
                else sum[j]=sum[j+v[j]]+1,nex[j]=nex[j+v[j]];
        }
        in(m);
        while(m--) {
            int a,b,c; in(a),in(b),b++;
            if(a==1) printf("%d
    ",query(b));
            else in(c),change(b,c);
        }
    }
    
  • 相关阅读:
    单例模式-静态内部类方式
    单例模式-懒汉式(双重检验)
    单例模式-懒汉式
    sonarqube7.2版本web api简析
    sonarqube集成maven插件,上传扫描结果
    sonarQube快速入门7.2版本下载pmd插件,并设置只使用pmd规则
    gradle使用dokka插件出现Exception while loading package-list from ExternalDocumentationLinkImp
    让linux后解压的资源权限就是777(工作笔记)
    java并发 无锁cas的最简单理解
    java 必须要懂点的包 今日研究小结
  • 原文地址:https://www.cnblogs.com/real-l/p/9768940.html
Copyright © 2011-2022 走看看