Codeforces Round 916 (Div. 3) 前6题

A. Problemsolving Log

题目链接

题目大意

给定一个字符串,统计其中出现次数大于其在字母表位次的字母个数,例如A需要出现1次,Z需要出现26次

题解

开map记录每个字母出现多少次,满足条件的输出,阅读能力太差了,签到题写半天

代码

#include<iostream>
#include<map>
#include<cstring>

using namespace std;

string s;
map<char,int>mp;

int main()
{
	int t;
	cin>>t;
	
	while(t--)
	{
	  mp.clear();
	  int n;
	  cin>>n>>s;
	  int res=0;
	  for(int i=0;i<s.size();i++)
	  {
	  	mp[s[i]]++;
	  }	
	for(char c='A';c<='Z';c++)
	{
		if(mp[c]>=c-'A'+1) res++;
		
	}
		cout<<res<<endl;
		//cout<<'A'-64;
	}
	
	return 0;
}

B. Preparing for the Contest

题目链接

题目大意

给定从1-n,n个数字,输出时要求其中有k个数字比前一个数大

题解

此题为构造题,我们找出通解即可,不难发现n个升序的数,可提供n-1个比前一个数大的数

那么我们需要k+1个升序的数,n-(k+1)个降序的数

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
using namespace std;

#define long long ll;
typedef pair<int,int>PII;

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,k;
		cin>>n>>k;
		for(int i=1,j=n;i<=n-k-1;i++) cout<<j--<<" ";
		for(int i=1,j=1;i<=k+1;i++) cout<<j++<<" ";
		cout<<endl;
		
	}
	return 0;
}

C. Quests

题目链接

题目大意

一共有n个任务,最多可以完成k个,每个任务有首次完成奖励和重复完成奖励,每个任务可以重复完成,只有做完前一天的任务才能做下一天的任务,求可获得的最大的奖励

题解

用贪心的思想,对于做到第i个任务可以获得的最大奖励为:1-i个任务的首次完成奖励(这里可以用前缀和计算)+(k-i)*1-i个任务中重复完成奖励最大的任务奖励

然后我们枚举所有的可能做到的任务,取奖励最大值即可

代码

#include<iostream>
#include<algorithm>

using namespace std;
const int N=2e5+10;
typedef long long ll;
ll  a[N],b[N];
ll s[N];
ll f[N];//表示只解锁第i个任务获得的最大经验值
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		ll n,k;
		cin>>n>>k;
		for(ll i=1;i<=n;i++) 
		{
			scanf("%lld",&a[i]);
			s[i]=s[i-1]+a[i];//1-i个任务的首次完成奖励之和
			
		}
		
		for(ll i=1;i<=n;i++) scanf("%lld",&b[i]);
		ll maxn=-1e9;
		for(ll i=1;i<=n;i++)
		{
			
			maxn=max(maxn,b[i]);
			f[i]=s[i]+maxn*(k-i);
		}
		
		ll ans=-1e9;//这里枚举能做的任务数一定不超过任务总数与可以完成的任务数
		for(ll i=1;i<=k && i<=n;i++) ans=max(ans,f[i]);
		cout<<ans<<endl;
		
	}
	
	
  return 0;
}

D. Three Activities

题目链接

题目大意

给定三个数组,求三个下标不同的数之和

题解

其实没有必要枚举全部元素,不难发现符合条件的三个数一定在每个数组前三大的数中产生,所以我们将三个数组降序排序,并枚举每个数组前三大的数,取和最大且下标不同的即可。这里使用了结构体存储下标

代码

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

const int N=2e5+10;

struct edge{
	int v,ii;//值,下标
	bool operator < (edge const &t) const//重载大于号,降序排
	{
		return v>t.v;
	}
}a[N],b[N],c[N];


int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i].v,a[i].ii=i;
		for(int i=1;i<=n;i++) cin>>b[i].v,b[i].ii=i;
		for(int i=1;i<=n;i++) cin>>c[i].v,c[i].ii=i;
		
		sort(a+1,a+n+1);
		sort(b+1,b+n+1);
		sort(c+1,c+n+1);
		int maxn=0;
		
		for(int i=1;i<=3;i++)
		{
			for(int j=1;j<=3;j++)
			{
				for(int z=1;z<=3;z++)
				{
					if(a[i].ii==b[j].ii || b[j].ii==c[z].ii || a[i].ii==c[z].ii) continue;
					int ans=a[i].v+b[j].v+c[z].v;
					maxn=max(maxn,ans);
				}
			}
		}
		
		cout<<maxn<<endl;
	}
	
	
	return 0;
}

E2. Game with Marbles (Hard Version)

题目链接 

E1为E2数据弱化版

题目大意

a和b都有n种颜色不同的弹珠,每人轮流行动,每次行动可以选择一种颜色,将对方该种颜色的弹珠清0,自己该种颜色的弹珠-1,前提是两人都至少有一颗该种颜色的弹珠。当两人都无法进行操作,即两人没有数量都大于1的相同颜色弹珠时,游戏结束。最后的分数a的弹珠数量减b的弹珠数量。a想要将分数最大化,b想要将分数最小化,假设两人都聪明绝顶,每次行动一定是对自己最优的,求最终分数。

题解

我们假设一组数据

a:  x   u

b:  y   v

则当a选择第一种颜色时,a可获得分数为x-1,b可获得的分数为v-1,则最终分数为x-v

当a选择第二种颜色时,a可获得的分数为u-1,b可获得的分数为y-1,则最终分数为u-y

所以为了最大化分数,当x-v>u-y时a会选择操作第一种颜色的弹珠,当x-v小于u-y时,a会选择操作第二种颜色的弹珠。移项之后即x+y>u+v时会选择第一种颜色的弹珠,x+y<u+v时会选择第二种颜色的弹珠。所以我们发现两人每次选择的弹珠颜色,一定是两人拥有相同颜色弹珠的数目之和最大的弹珠颜色。

也就是说两人一定轮流操作弹珠数量之和最大的弹珠,那么我们可以计算出每种颜色弹珠的数量之和,并降序排序。模拟两人轮流取弹珠的过程,由于最终分数为a的弹珠数减b的弹珠数,所以a对最总分数的贡献为加上该种颜色弹珠可获得的·分数,而b对最终分数的共享为减去该种颜色弹珠可获得的分数。而每人对该种颜色弹珠可获得的分数即自己拥有的该种颜色弹珠的数量减一。

代码

// Problem: E1. Game with Marbles (Easy Version)
// Contest: Codeforces - Codeforces Round 916 (Div. 3)
// URL: https://codeforces.com/contest/1914/problem/E1
// Memory Limit: 256 MB
// Time Limit: 3500 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>

#define ll long long
using namespace std;


typedef pair<int,int>PII;

const int N=2e6+10;
struct edge{
	int a,b;//a和b分别拥有该种颜色弹珠的数量
	int sum;//该种颜色弹珠数量之和
	bool operator < (edge const &t) const //重载大于号,降序排
	{
		return sum>t.sum;
	}
};

edge f[N];

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		ll res=0;//答案
		int n;
		cin>>n;
		for(int i=1;i<=n;i++) cin>>f[i].a;
		for(int i=1;i<=n;i++) cin>>f[i].b,f[i].sum=f[i].a+f[i].b;
		sort(f+1,f+n+1);
		for(int i=1;i<=n;i++)
		{
			if(i%2) res+=f[i].a-1;//a的回合获得的分数为a弹珠数量-1
	        else res-=f[i].b-1;//b的回合获得的分数为b弹珠数量-1
		}
		cout<<res<<endl;
	}
	return 0;
}

谨记大佬赛后写题解的教诲,遂写下第一篇题解,希望自己能坚持下去。

  • 41
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces Round 894 (Div. 3) 是一个Codeforces举办的比赛,是第894轮的Div. 3级别比赛。它包含了一系列目,其中包括目E. Kolya and Movie Theatre。 根据目描述,E. Kolya and Movie Theatre问要求我们给定两个字符串,通过三种操作来让字符串a等于字符串b。这三种操作分别为:交换a中相同位置的字符、交换a中对称位置的字符、交换b中对称位置的字符。我们需要先进行一次预处理,替换a中的字符,然后进行上述三种操作,最终得到a等于b的结果。我们需要计算预处理操作的次数。 根据引用的讨论,当且仅当b[i]==b[n-i-1]时,如果a[i]!=a[n-i-1],需要进行一次操作;否则不需要操作。所以我们可以遍历字符串b的半部分,判断对应位置的字符是否与后半部分对称,并统计需要进行操作的次数。 以上就是Codeforces Round 894 (Div. 3)的简要说明和目E. Kolya and Movie Theatre的要求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Codeforces Round #498 (Div. 3) (A+B+C+D+E+F)](https://blog.csdn.net/qq_46030630/article/details/108804114)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Codeforces Round 894 (Div. 3)A~E解](https://blog.csdn.net/gyeolhada/article/details/132491891)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值