• P3203 弹飞绵羊-分块


    P3203 弹飞绵羊-分块

    观察数据范围,发现可以分块。只需要处理每个点跳出所在块后的位置和次数即可。目的是为了加速查询并降低修改复杂度。

    对于修改,重构整个块内信息即可。

    时间复杂度正确的一批

    具体实现也挺简单。注意重构时从后往前贡献即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read(){
    	int w=0,x=0;char c=getchar();
    	while(!isdigit(c))w|=c=='-',c=getchar();
    	while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
    	return w?-x:x;
    }
    namespace star
    {
    	const int maxn=2e5+10;
    	int n,N,out[maxn],cos[maxn],a[maxn],belong[maxn],l[maxn],r[maxn];
    	void sudo(int l,int r){for(int i=r;i>=l;i--)if(i+a[i]>n or belong[i+a[i]]!=belong[i])out[i]=i+a[i],cos[i]=1;else out[i]=out[i+a[i]],cos[i]=1+cos[i+a[i]];}
    	inline void work(){
    		n=read();
    		N=sqrt(n);
    		for(int i=1;i<=n;i++)
    			belong[i]=(i-1)/N+1;
    		for(int i=1;i<=n;i++){
    			if(!l[belong[i]])l[belong[i]]=i;
    			r[belong[i]]=i;
    		}
    		for(int i=1;i<=n;i++)a[i]=read();
    		sudo(1,n);
    		int q=read();
    		while(q--){
    			if(read()==1){
    				int sum=0,pos=read()+1;
    				while(pos<=n)sum+=cos[pos],pos=out[pos];
    				printf("%d
    ",sum);
    			}else{
    				int pos=read()+1;
    				a[pos]=read();
    				sudo(l[belong[pos]],r[belong[pos]]);
    			}
    		}
    	}
    }
    signed main(){
    	star::work();
    	return 0;
    }
    

    那我要是想知道最后弹飞前的点在哪呢?

    我们只需要在重构的时候记录一下从哪来的就好了。

    双倍经验:CF13E

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read(){
    	int w=0,x=0;char c=getchar();
    	while(!isdigit(c))w|=c=='-',c=getchar();
    	while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
    	return w?-x:x;
    }
    namespace star
    {
    	const int maxn=2e5+10;
    	int n,N,out[maxn],last[maxn],cos[maxn],a[maxn],belong[maxn],l[maxn],r[maxn];
    	void sudo(int l,int r){for(int i=r;i>=l;i--)if(i+a[i]>min(n,r))out[i]=i+a[i],last[i]=i,cos[i]=1;else out[i]=out[i+a[i]],last[i]=last[i+a[i]],cos[i]=1+cos[i+a[i]];}
    	inline void work(){
    		n=read();
    		int q=read();
    		N=sqrt(n);
    		for(int i=1;i<=n;i++)
    			belong[i]=(i-1)/N+1;
    		for(int i=1;i<=n;i++){
    			if(!l[belong[i]])l[belong[i]]=i;
    			r[belong[i]]=i;
    		}
    		for(int i=1;i<=n;i++)a[i]=read();
    		for(int i=1;i<=belong[n];i++)sudo(l[i],r[i]);
    		while(q--){
    			if(read()==1){
    				int sum,pos,lpos;
    				sum=0,pos=lpos=read();
    				while(pos<=n)sum+=cos[pos],lpos=last[pos],pos=out[pos];
    				printf("%d %d
    ",lpos,sum);
    			}else{
    				int pos=read();
    				a[pos]=read();
    				sudo(l[belong[pos]],r[belong[pos]]);
    			}
    		}
    	}
    }
    signed main(){
    	star::work();
    	return 0;
    }
    
  • 相关阅读:
    [转载]PhotoShop性能优化
    SVN常用命令
    [转载]SVN使用教程
    MyEclipse Java Build Path详解
    MyEclipse安装后需要进行的配置
    c#中base64加密解密
    C# MD5 加密
    C# http Post 方法
    EPF与Myeclipse 增强代码自动智能提示
    汉字代码手册
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/13775714.html
Copyright © 2020-2023  润新知