Educational Codeforces Round 69 (Rated for Div. 2)

A. DIY Wooden Ladder

签到题,比较现在能够有的阶梯数和规定的阶梯数就可以了

    # include <bits/stdc++.h>
    using namespace std;
     
    const int MAXN=1e5+100;
    int a[MAXN];
    int cmp(int a,int b)
    {
    	return a>b;
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--){
    		int n;
    		int k=0;
    		scanf("%d",&n);
    		for(int i=1;i<=n;i++){
    			scanf("%d",&a[i]);
    		}
    		sort(a+1,a+n+1,cmp);
    		int aa=a[1],bb=a[2];
    		//cout<<"@@"<<aa<<" "<<bb<<endl;
    		int shortt=min(aa,bb)-1;
    		//cout<<"###"<shortt<<endl;
    		for(int i=3;i<=n;i++){
    			if(a[i]>=1){
    				k++;
    			}
    		}
    		k=min(shortt,k);
    		cout<<k<<endl;
    	} 
    	
    	return 0;
     } 

B. Pillars

只要从最大的那个开始向两边都是降序就可以移动,否则不行,(就是一下移动左边的盘,一下移动右边的盘。可能没有讲清楚,画个样例,自己稍微感受一下)

    # include <bits/stdc++.h>
    using namespace std;
     
    const int MAXN=2e5+100;
    int a[MAXN];
    int main()
    {
    	int n;
    	int flag=1;
    	scanf("%d",&n);
    	int maxx=0,maxi=1;
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		if(a[i]>maxx){
    			maxx=a[i];
    			maxi=i;
    		}
    	}
    	int aa=a[maxi];
    	for(int i=maxi+1;i<=n;i++){
    		if(aa>a[i]){
    			aa=a[i];
    		}else{
    			flag=0;
    			break;
    		}
    	}
    	int bb=a[maxi];
    	for(int i=maxi-1;i>=1;i--){
    		if(bb>a[i]){
    			bb=a[i];
    		}else{
    			flag=0;
    			break;
    		}
    	}
    	if(flag){
    		printf("YES");
    	}else{
    		printf("NO");
    	}
    	
    	return 0;
    }

C. Array Splitting

假设选取做区间右端点的数分别是a,b,c,d,先假设这四个好了,那么上诉式子就是a[a]-a[1]+a[b]-a[a+1]+a[c]-a[b+1]+a[d]-a[c+1],(a[d]==a[n])移项可以知道(a[n]-a[1])+(a[a]-a[a+1])+(a[b]-a[b+1])+(a[c]-a[c+1]),而a[n]-a[1]是定的,所以只要后面最小就可以了

    # include <bits/stdc++.h>
    using namespace std;
     
    const int MAXN=3e5+100;
    int a[MAXN];
    pair<int,int> p[MAXN];
    int main()
    {
    	int n,k;
    	int ans=0;
    	scanf("%d %d",&n,&k);
    	
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    	}
    	
    	if(k==n){
    		printf("0");
    	}else if(k==1){
    		ans=a[n]-a[1];
    		printf("%d",ans);
    	}else{
    		ans=a[n]-a[1];
    		for(int i=1;i<n;i++){
    			p[i].first=a[i]-a[i+1];
    			p[i].second=i;
    		}
    		sort(p+1,p+n+1);
    		for(int i=1;i<k;i++){
    			ans+=p[i].first;
    		}
    		printf("%d",ans);
    	}
    	
    	return 0;
    }

D. Yet Another Subarray Problem

题目中是向上取整的符号,希望读者没有和菜鸡我一样看成向下取整(还被学长批评了一顿,刚好被教练看到,丢人啊 )。读者可以去做一下对大子段和(应该也可以叫最大区间和),这里就是把区间长度限定为m

    # include <bits/stdc++.h>
    using namespace std;
     
    const int MAXN=3e5+100;
    typedef long long LL;
    LL a[MAXN];
    LL pre[MAXN];
    LL dp[MAXN][20];
    int main()
    {
    	int n,m,k;
    	scanf("%d %d %d",&n,&m,&k);
    	
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&a[i]);
    		pre[i]=pre[i-1]+a[i];
    	}
    	LL ans=0;
    	for(int i=1;i<=n;i++){//枚举每一个位置
    		for(int j=1;j<=m;j++){//从这个位置向前取j个,
    			if(j<=i){//这个保证每一次都是要减k的
    				dp[i][j]=max(pre[i]-pre[i-j],pre[i]-pre[i-j]+dp[i-j][m])-k;
    			}
    			ans=max(dp[i][j],ans);
    		}
    	}
    	
    	
    	cout<<ans<<endl;
    	return 0;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值