• #6435. 「PKUSC2018」星际穿越


    考场上写出了70分,现在填个坑

    比较好写的70分是这样的:(我考场上写的贼复杂)

    (L(i)=min_{j=i}^nl(j))

    那么从i开始向左走第一步能到达的就是([l(i),i-1])(显然)

    第二步能到达的是([L(l(i)),l(i)-1])

    为什么呢,因为i一开始可以直接向左,也可以先向右走到(l)最小的位置然后向左,这时能跳到的区间就是([L(i),i])

    如果(L(l(i))=L(i))显然这是一种方案,但是有可能(L(l(i))<L(i)),既然小了肯定是(l(k)(kin[l(i),i)))这一部分(<L(i)),那么当然也是可行的

    后面就是([L(L(cdots L(l(i))cdots)),上一个的左端点])了,一直推下去。

    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    typedef long long ll;
    il int gi(){
    	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;
    }
    int l[300010],L[300010];
    ll D[5010][5010];
    //D[i][j]表示从i开始到[j,i-1]的跳的次数之和
    int main(){
    	int n=gi();
    	for(int i=2;i<=n;++i)l[i]=gi();
    	L[n]=l[n];for(int i=n-1;i>1;--i)L[i]=std::min(l[i],L[i+1]);
    	for(int i=2;i<=n;++i){
    		int x=l[i],lst=i;
    		for(int j=x;j<lst;++j)D[i][j]=1;
    		int d=1;
    		while(x!=1){
    			lst=x;x=L[x];++d;
    			for(int j=x;j<lst;++j)D[i][j]=d;
    		}
    		for(int j=1;j<i;++j)D[i][j]+=D[i][j-1];
    	}
    	int q=gi(),l,r,x;
    	while(q--){
    		l=gi(),r=gi(),x=gi();
    		ll A=D[x][r]-D[x][l-1],B=r-l+1,g=std::__gcd(A,B);
    		printf("%lld/%lld
    ",A/g,B/g);
    	}
    	return 0;
    }
    

    优化很显然是倍增,很容易想到(f[i][j])设为(i)位置向前跳(L(i))(2^j)次。

    再来一个(g[i][j])设为(i)位置向前跳(2^j)次,这中间每个位置跳的次数的和。随便理解一下就行了。

    
    
    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    typedef long long ll;
    il int gi(){
    	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;
    }
    int l[300010],L[300010];
    int f[19][300010];
    ll g[19][300010];
    il ll solve(int x,int y){
    	if(l[x]<=y)return x-y;
    	ll ret=x-l[x];int i,j;
    	x=l[x];
    	for(i=18,j=1;~i;--i)
    		if(f[i][x]>=y){
    			ret+=g[i][x]+j*(x-f[i][x]);
    			j+=1<<i;
    			x=f[i][x];
    		}
    	return ret+(x-y)*(j+1);
    }
    int main(){
    	int n=gi();
    	for(int i=2;i<=n;++i)l[i]=gi();
    	L[n]=l[n];for(int i=n-1;i>1;--i)L[i]=std::min(l[i],L[i+1]);
    	for(int i=1;i<=n;++i)f[0][i]=L[i],g[0][i]=i-L[i];
    	for(int i=1;i<19;++i)
    		for(int j=1;j<=n;++j){
    			f[i][j]=f[i-1][f[i-1][j]];
    			g[i][j]=g[i-1][j]+g[i-1][f[i-1][j]]+(1<<i-1)*(f[i-1][j]-f[i][j]);
    		}
    	int q=gi(),l,r,x;
    	while(q--){
    		l=gi(),r=gi(),x=gi();
    		ll A=solve(x,l)-solve(x,r+1),B=r-l+1,g=std::__gcd(A,B);
    		printf("%lld/%lld
    ",A/g,B/g);
    	}
    	return 0;
    }
    
  • 相关阅读:
    win8装oracle 10g 弹出:环境变量path的值超过1023字符,无法设置改值
    Modern UI for WPF 开源项目(3):用模板创建我的第一个Modern UI app
    安装oracle11G,10G时都会出现:注册ocx时出现OLE初始化错误或ocx装载错误对话框
    win8快捷键
    Win7/Win8 系统下安装Oracle 10g 提示“程序异常终止,发生未知错误”的解决方法
    Delphi FireDAC 连接SQL Server一些要注意的地方
    Delphi XE5 for Android (四)
    Delphi D10.X VCL和FireMonkey之间的常见差异介绍
    delphi给App授予权限
    github无法登陆的解决办法
  • 原文地址:https://www.cnblogs.com/xzz_233/p/10022691.html
Copyright © 2020-2023  润新知