Codeforces Round 917 (Div. 2)(Codeforces日记)

目录

A. Least Product

题目大意:

题解:

AC代码:

B. Erase First or Second Letter

题目大意:

题解:

AC代码:

C. Watering an Array

题目大意:

题解:

AC代码:

总结:


A. Least Product

题目大意:

给你一个数组,让你求出数组乘积的最小值。另外你可以执行多次操作(将数组中任意一个数变成0),输出你将数组乘积变成最小执行的操作次数。

题解:

因为操作只能将数字变成0,所以在输入过程中,先判断原数组有没有0,如果有0直接输出操作次数0,如果没有0,则判断负数个数,如果为奇数则不用操作(即操作次数0),如果为偶数,则将任意一个数变成0即可,操作次数1,正数不用考虑。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl "\n";
int aa[200100];
void solve()
{
	int n,b=0,flag=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>aa[i];
		if(aa[i]<0)
		b++;
		if(aa[i]==0)
		flag=1;
	}
	if(flag){
		cout<<0<<endl;
	}
	if(b%2){
		cout<<0<<endl;
	}
	else{
		cout<<1<<endl;
		cout<<1<<" "<<0<<endl;
	}
	return ;
}
signed main()
{
	IOS
	int t=1;
	cin>>t;
	while(t--)
	solve();
    return 0;
}

B. Erase First or Second Letter

题目大意:

给你一个字符串,并且你有两种操作:1.将首个字符删除。2.将第二个字符删除。操作次数不限,在你所有的操作中,一共能弄出多少种不同的非空字符串。

题解:

因为操作是从头进行,所以可以得出一个结论:前面出现过的字符,后面再出现,它之后的操作都和前者是重复的,所以只需要判断从头到尾一共出现多少不同的字符,并且每次出现一个不同的,就将其所在的位置和后面的字符数量相加。

AC代码:

#include<bits/stdc++.h>
using namespace std;
//#define int long long 
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl "\n";
int a[200100];
void solve()
{
	int n,ans=0,sum=0;
	cin>>n;
	string x;
	cin>>x;
	map<char,int>m;
	for(int i=0;i<x.size();i++){
		if(!m[x[i]]){
			sum+=n-i;
		}
		m[x[i]]++;
	}
	cout<<sum<<endl;
	return ;
}
signed main()
{
	IOS
	int t=1;
	cin>>t;
	while(t--)
	solve();
    return 0;
}

C. Watering an Array

题目大意:

给你a和b两个数组和一个操作天数d,你有两个操作:1.在数组b的前b[i]个元素,每个加1。2.计算a数组中a[i]==i的个数,并加到你的分数上,然后将a数组全部置为零。每天只能进行一个操作,另外数组b是呈环状的,天数如果大于b的长度,从b的第一个元素重新开始。

题解:

可以先在输入的时候计算初始状态下a[i]==i的个数ans,并且设置一个循环遍历每次进行操作的分数,因为每次操作可以选择加数或者加分置零两种,所以循环次数应为min(2*n+1,d),另外每次循环遍历a数组前b[i]个数,分加数前和后两次判断,加数前a[i]==i的话,分数-1,加分后a[i]==i的话,分数+1。然后每次用sum=max(sum,ans+(d-i)/2)遍历最大得分。提要:因为一般情况下,是直接在第一次操作直接加分置零,然后每两次操作加1分,所以是ans+(d-1)/2,但是如果第一天不加分置零的话,分数就是ans+(d-i)/2;

AC代码:

#include<bits/stdc++.h
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
#define endl '\n'
int a[200100],b[200100];
void Solved() {
	
	int n,k,d,ans=0,sum=0;
	cin>>n>>k>>d;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(a[i]==i)
		sum++;
	}
	for(int i=1;i<=k;i++){
		cin>>b[i];
	}
	b[0]=b[k];
	for(int i=1;i<=min(2*n+1,d);i++){
	    ans=max(ans,(d-i)/2+sum);
		int x=b[i%k];
		for(int j=1;j<=x;j++){
			if(a[j]==j){
				sum--;
			}
			a[j]++;
			if(a[j]==j){
				sum++;
			}
		}
	}
	cout<<ans<<endl;
	return ;
}
signed main(void) {
    IOS
	int ALL = 1; 
	cin >> ALL;
	while(ALL -- ) Solved();
    return 0;
}

总结:

还是需要锻炼思维,就类似于C的状态转换,想出来直接就秒了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值