zoukankan      html  css  js  c++  java
  • 【codeforces】【比赛题解】#940 CF Round #466 (Div. 2)

    人生的大起大落莫过如此,下一场我一定要回紫。


    【A】Points on the line

    题意:

    一个直线上有(n)个点,要求去掉最少的点,使得最远两点距离不超过(d)。

    题解:

    暴力两重for,更新答案。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define F(i,a,b) for(int i=(a);i<=(b);++i)
    int n,q,ans=0;
    int a[100001];
    int main(){
    	scanf("%d%d",&n,&q);
    	F(i,1,n) scanf("%d",a+i);
    	sort(a+1,a+n+1);
    	F(i,1,n){
    		int xx=a[i], kk=-1;
    		F(j,i,n){
    			if(a[j]-xx>q) break;
    			kk=j;
    		}
    		ans=max(ans,kk-i+1);
    	}
    	printf("%d",n-ans);
    	return 0;
    }
    

    【B】Our Tanya is Crying Out Loud

    题意:

    一个数(n),每次你可以花费(A)的代价把它除以(k)(如果(k|n)),或者花费(B)的代价把它减一。问把这个数变成1的最少代价。

    题解:

    暴力上,不能除减到能除为止,能除看是除了花费少还是不除花费少。

    注意特判(k=1)。

    #include<cstdio>
    #define ll long long
    int n,k,A,B;
    ll ans;
    int main(){
    	scanf("%d%d%d%d",&n,&k,&A,&B);
    	if(k==1) {printf("%lld",(ll)(n-1)*A);return 0;}
    	while(n!=1){
    		int x=n/k*k;
    		if(x==0) {ans+=(ll)(n-1)*A; break;}
    		if(n!=x) ans+=(ll)(n-x)*A, n=x;
    		else{
    			x=n/k;
    			if((ll)(n-x)*A<=B) ans+=(ll)(n-x)*A;
    			else ans+=B;
    			n=x;
    		}
    	}
    	printf("%lld",ans);
    	return 0;
    }
    

    【C】Phone Numbers

    题意:

    限定字符集,求长度为(k)的,字典序比给定长度为(n)的字符串大的最小的字符串。

    题解:

    ①(k>n)时,在原串后补上最小的字符。

    ②(k<=n)时,答案为原串的前(k)位+1,即比原串(k)位前缀大的第一个字符串。

    #include<cstdio>
    #define F(i,a,b) for(int i=(a);i<=(b);++i)
    #define F2(i,a,b) for(int i=(a);i<(b);++i)
    int n,k,tot;
    int px[150];
    bool used[150];
    char str[100010],use[30];
    char ans[100010];
    int main(){
    	scanf("%d%d",&n,&k);
    	scanf("%s",str);
    	F2(i,0,n) used[str[i]]=1;
    	F(i,1,140) if(used[i]) use[++tot]=i;
    	F(i,1,tot) px[use[i]]=i; 
    	if(k>n){
    		printf("%s",str);
    		F(i,n+1,k) printf("%c",use[1]);
    		return 0;
    	}
    	F2(i,0,k) ans[i]=str[i]; ans[k]='';
    	int x=k-1;
    	while(px[ans[x]]==tot){
    		ans[x]=use[1];
    		--x;
    	}
    	ans[x]=use[px[ans[x]]+1];
    	printf("%s",ans);
    	return 0;
    }
    

    【D】Alena And The Heater

    题意:

    已知长度为(n)的数组(a)和等长的01串(b),和通过(a)生成(b)的方法:

    (b_1=b_2=b_3=b_4=0)

    对于(5le ile n)

    如果(a_i,a_{i-1},a_{i-2},a_{i-3},a_{i-4}>r) 并且(b_{i-1}=b_{i-2}=b_{i-3}=b_{i-4}=1),那么(b_i=0)

    如果(a_i,a_{i-1},a_{i-2},a_{i-3},a_{i-4}<l) 并且(b_{i-1}=b_{i-2}=b_{i-3}=b_{i-4}=0),那么(b_i=1)

    如果以上两者均不满足,那么(b_i=b_{i-1})。

    试求出(l,r)的值。

    题解:

    可以看到,对计算有贡献的只有(b)中出现连续的4个相同数字的情况。

    通过这些情况,我们可以确定(l,r)的范围,进而求出(l,r)的可能值。

    因为题目保证有解,只需输出最极端的值((l_{min},r_{max}))即可。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define F(i,a,b) for(int i=(a);i<=(b);++i)
    int n,ansll=-1000000000,ansrr=1000000000;
    int a[100001];
    char b[100009];
    int main(){
    	scanf("%d",&n);
    	F(i,1,n) scanf("%d",a+i);
    	scanf("%s",b+1);
    	F(i,5,n){
    		if(b[i-4]==b[i-3]&&b[i-3]==b[i-2]&&b[i-2]==b[i-1]){
    			if(b[i-1]=='0'){
    				int x=max(max(max(max(a[i],a[i-1]),a[i-2]),a[i-3]),a[i-4]);
    				if(b[i]=='1'){
    					//l > max(a 1~5)
    					ansll=max(ansll,x+1);
    				}
    			}
    			else{
    				int x=min(min(min(min(a[i],a[i-1]),a[i-2]),a[i-3]),a[i-4]);
    				if(b[i]=='0'){
    					//r < min(a 1~5)
    					ansrr=min(ansrr,x-1);
    				}
    			}
    		}
    	}
    	printf("%d %d",ansll,ansrr);
    	return 0;
    }
    

    【E】Cashback

    题意:

    给定一个长度为(n)的数组(a)和一个常数(c)。你可以把(a)数组分割成连续的若干段,每一段的代价分别计算:

    对于长度为(len)的一段,其代价为其元素总和,减去最小的(left lfloor frac{len}{c} ight floor)个元素。

    求最小总代价。

    题解:

    既然要让代价最小,我们转化为求最大的价值,再用所有的元素和减去这个价值即可。

    那就变成了长度为(len)的一段,其价值为最小的(left lfloor frac{len}{c} ight floor)个元素的和。

    首先我们注意到一个结论:有贡献价值的分段,其长度正好为(c)时,没有其他方法比它更优。

    证明请自行脑补……因为我也没想清楚,当时考场上瞎猜的结论,有兴趣的读者不妨看看http://www.cnblogs.com/kkkkahlua/p/8468896.html

    那么,我们通过单调队列处理出每个长为(c)的区间的最小值,记为(b)数组。

    那么有DP方程(f[i]=(max_{j=1}^{i-c}f[i])+b[i-c+1]),表示前(i)个数,最后一个区间必须选取的最大价值,答案为(Sum-max(f[i]))。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define F(i,a,b) for(int i=(a);i<=(b);++i)
    #define ll long long
    int n,c;
    int a[100009],b[100009];
    int que[100009],l=1,r=0;
    ll sum,f[100009],g[100009];
    int main(){
    	scanf("%d%d",&n,&c);
    	F(i,1,n) scanf("%d",a+i);
    	F(i,1,n) sum+=a[i];
    	if(c>n) {printf("%lld",sum); return 0;}
    	F(i,1,c){
    		while(l<=r&&a[que[r]]>=a[i]) --r;
    		que[++r]=i;
    	} b[1]=a[que[l]];
    	F(i,c+1,n){
    		if(que[l]<=i-c) ++l;
    		while(l<=r&&a[que[r]]>=a[i]) --r;
    		que[++r]=i;
    		b[i-c+1]=a[que[l]];
    	}
    	F(i,1,n-c+1){
    		if(i<=c) f[i]=b[i];
    		else{
    			f[i]=b[i]+g[i-c];
    		}
    		g[i]=max(g[i-1],f[i]);
    	}
    	printf("%lld",sum-g[n-c+1]);
    	return 0;
    }
    
  • 相关阅读:
    Java Native Method
    SQL语句优化
    Ibatis的环境搭建以及遇到的问题解决
    Java 构建器
    SpringMVC自定义视图 Excel视图和PDF视图
    java 枚举的常见使用方法
    mysql 根据某些字段之和排序
    MFC The Screen Flickers When The Image Zoomed
    How To Debug Qmake Pro File
    Gcc And MakeFile Level1
  • 原文地址:https://www.cnblogs.com/PinkRabbit/p/8469943.html
Copyright © 2011-2022 走看看