bzoj2002 弹飞绵羊【分块】

来源:互联网 发布:怎么在阿里云里备案 编辑:程序博客网 时间:2024/05/16 11:19

解题思路:

我们可以在分块后维护每个位置弹出该块所需步数和弹到的位置,这样查询和修改都是O(n)的了。

#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<ctime>#include<vector>#include<set>#include<map>#include<queue>#define ll long longusing namespace std;int getint(){    int i=0,f=1;char c;    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());    if(c=='-')f=-1,c=getchar();    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';    return i*f;}const int N=200005;int n,m,S,cnt;int k[N],st[N],pt[N],id[N],l[N];int calc(int x){    int res=0;    for(;x;x=pt[x])res+=st[x];    return res;}void modify(int x){    k[x]=getint();    for(int i=x;i>=l[id[x]];i--)    {        if(i+k[i]>n)st[i]=1,pt[i]=0;        else if(id[i]!=id[i+k[i]])st[i]=1,pt[i]=i+k[i];        else st[i]=st[i+k[i]]+1,pt[i]=pt[i+k[i]];    }}int main(){    //freopen("lx.in","r",stdin);    n=getint();S=sqrt(n);    for(int i=1;i<=n;i++)k[i]=getint();    if(n%S)cnt=n/S+1;    else cnt=n/S;    for(int i=1;i<=cnt;i++)l[i]=(i-1)*S+1;    for(int i=1;i<=n;i++)id[i]=(i-1)/S+1;    for(int i=n;i;i--)    {        if(i+k[i]>n)st[i]=1;        else if(id[i]!=id[i+k[i]])st[i]=1,pt[i]=i+k[i];        else st[i]=st[i+k[i]]+1,pt[i]=pt[i+k[i]];    }    m=getint();    while(m--)    {        int op=getint(),x=getint()+1;        if(op==1)cout<<calc(x)<<'\n';        else modify(x);    }    return 0;}
原创粉丝点击