Codeforces Round 953 (Div. 2)

A. Alice and Books

题目大意:有n本书,每本书都有一个页数a,把书分成两组,这两组的最大编号的书的页数相加最大是多少?

思路:第n本书一定是其中一组的编号最大的书,然后再剩下书中的找到页数最多的书k,编号比k 大的书可以放到第n本书所在的那组去。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[107];
int main()
{
	int t;
	cin>>t;
	while(t--){
		int n;
		cin>>n;
		for(int i=0;i<n;i++){
			cin>>a[i];
		}
		sort(a,a+n-1);
		ll ans=a[n-1]+a[n-2];
		cout<<ans<<endl;
	}
	return 0;
}

B. New Bakery

题目大意:鲍勃开面包店,要卖n个面包,前k个面包按b-i+1促销,其余按a价出售。k是[0,n]中的任意一个数,求n个面包的最大利润。(i>=1)

思路:只要卖第i个面包是max(a,b-i+1)最后的利润就是最大值,所以只要让保证i<=k时b-i+1>=a就行了。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
	int t;
	cin>>t;
	while(t--){
		ll n,a,b;
		cin>>n>>a>>b;
		if(a>=b){
			ll ans=a*n;
			cout<<ans<<endl;
		}else{
			ll k=b-a;
			if(n<k)k=n;
			ll ans=(n-k)*a;
			ans+=k*b-((k-1)*k/2);
			cout<<ans<<endl;
		}
	}
	return 0;
}

C. Manhattan Permutations

题目大意:我们称一个排列的曼哈顿值为表达式 |p1−1|+|p2−2|+…+|pn−n| 的值。给你两个整数 n 和 k。找到一个长度为 n 的排列 p,使得它的曼哈顿值等于 k,或者确定不存在这样的排列。

思路:首先,当排列p递减时,曼哈顿值最大,我们可以分析,发现曼哈顿值一定为偶数。所以我们就能判断曼哈顿值存不存在。然后用双指针头尾同时扫描,如果交换产生的曼哈顿值小于k,就交换,同时k也减去增加的曼哈顿值,否则的话,选一个指针移动一格。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[200007];
int main(){
	int t;
	cin>>t;
	while(t--){
		int n;
		ll ans=0,k;
		cin>>n>>k;
		for(int i=1,j=n;i<=n;i++,j--){
			a[i]=i;
			ans+=fabs(i-j);
		}
		if(k>ans||k&1)cout<<"No"<<endl;
		else{
			cout<<"Yes"<<endl;
			int l=1,r=n;
			while(l<r&&k!=0){
				int h=2*fabs(l-r);
				if(h<=k){
					swap(a[l],a[r]);
					k-=h;
					l++;r--;
				}else{
					l++;
				}
			}
			cout<<a[1];
			for(int i=2;i<=n;i++){
				cout<<" "<<a[i];
			}
			cout<<endl;
		}		
	}
	return 0;
}

D. Elections

题目大意:有 n 位候选人参加选举,编号从 1 到 n。第 i 位候选人有 ai 名粉丝会为他投票。此外还有c个人没投,这些人会投给编号最小的人。如果你不候选人i参加选举,那么他的ai票将会给到还能参加选举的编号最小的候选人。问对于每个 i 从 1 到 n,需要排除多少位候选人,以便候选人编号 i 赢得选举。(如果票数相同,编号最小的人赢)

思路:如果第i个人是编号最小的最多票数的人,那么就不用排除。否则,先把i前面的全部排除,因为这样才能让i成为编号最小的,从而改变它的值。如果这时候ai仍然不是最多的,那么就把最大的排除,这样ai就加上了最大的,ai就成为最大的了。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[200007],h[200007];
int main()
{
	int t;
	cin>>t;
	while(t--){
		int n;
		ll c;
		cin>>n>>c;
		a[0]=0;
		int m=0;	
		for(int i=1;i<=n;i++){
			cin>>a[i];
			if(i==1)a[i]+=c;
			if(a[m]<a[i])m=i;
		}
		h[n+1]=0;
		for(int i=n;i>=1;i--){
			h[i]=max(a[i],h[i+1]);
		}
		ll maxn=a[m];
		ll ans=0;
		int flag=0;
		for(int i=1;i<=n;i++){
			if(flag==1)cout<<" ";
			flag=1;
			ans+=a[i];
			if(i==m)cout<<0;
			else{
				if(ans>=h[i+1])cout<<i-1;
				else cout<<i;
			}
		}
		cout<<endl;
	}
	return 0;
}

        掉大分,还是写题太少了......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值