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;
    }
    
  • 相关阅读:
    python3监控网站状态
    暴力屏蔽80访问失败的用户
    python3爬取中国药学科学数据
    python3发邮件脚本
    OOP AOP
    lambda
    jni
    Gradle史上最详细解析
    supersocket 遇到的Failed to initialize 和 log4net用法
    在c#中利用keep-alive处理socket网络异常断开的方法
  • 原文地址:https://www.cnblogs.com/PinkRabbit/p/8469943.html
Copyright © 2011-2022 走看看