Codeforces Round #822 (Div. 2)(A-D)

1 篇文章 0 订阅

题目链接: Codeforces Round #822 (Div. 2)

A. Select Three Sticks

题意:

签到题,给你一个数组,你可以对每个数进行+1、-1的操作,要你找出最小操作数使得数组中有三个数可以组成等边三角形。

题解:

刚开始脑子没转过来,后面发现只要对数组排个序,然后利用滑动窗口的思想,三个值为一组开始滑动,每次找出三个数要组成等边三角形所需的最小操作数,并在所有三个为一组中找出最小值即可。

代码:

#include "cstdio"
#include "string"
#include"iostream"
#include"algorithm"
#include"queue"
#include"stack"
#include"map"
#include"cmath"

using namespace std;

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,a[305];
		cin>>n;
		int k=0;
		for(int i=0;i<n;i++)
			cin>>a[i];
		sort(a,a+n);
		int m=1000000000;
		for(int i=0;i<=n-3;i++)
		{
			int x;
			if(a[i]==a[i+1])
			{
				if(a[i+1]==a[i+2])
					x=0;
				else
					x=a[i+2]-a[i+1];
			}else
			{
				if(a[i+1]==a[i+2])
					x=a[i+1]-a[i];
				else
					x=a[i+2]-a[i];
			}
			m=min(m,x);
		}
		cout<<m<<endl;
	} 
	return 0;
}

B. Bright, Nice, Brilliant

题意:

这个题其实非常简单,只要读懂题目就可以(虽然说有点看不懂)。主要意思就是说,有一个金字塔,每层有与层数对应的房间数(1层一个房间,2层两个房间,3层三个房间......)。中间讲了一大堆废话来误导你,其实就是说,对于每个房间,你可以选择点亮或者不点亮。然后每个房间都有一个亮度值,这个亮度值的计算方法就是,从顶端开始,到达当前房间可以经过的所有房间中,有多少房间是点亮的(包括自己这个房间)。当前有一个“nice”金字塔的定义:每层的每个房间的亮度都是相同的。现在让你找出一个“nice”金字塔,并且每一层最左边的房间点亮数加在一起最大。

题解:

要让最左边房间点亮数加在一起最大,我们可以让最左边的所有房间都点亮,然后你会发现最左边房间的亮度值就是等于层数,这时候我们只要让这一层其他房间的亮度值也是等于层数就OK了。先考虑最右边的房间,到达最右边房间的路只有经过上面每一层的最右边房间,所以要使亮度值等于层数,就只有最右边每个房间都点亮。这时候你会发现其他所有房间都不用点亮,他们的亮度值就已经满足亮度值等于层数了,所以我们只要对每一层,左右输出1中间输出0就可以了。

代码:

#include "cstdio"
#include "string"
#include"iostream"
#include"algorithm"
#include"queue"
#include"stack"
#include"map"
#include"cmath"

using namespace std;

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

C. Removing Smallest Multiples

题意:

有一个数组S有n个整数满足a[i]=i(1≤i≤n),你可以选择一个正整数k,然后在S数组中删除k的最小倍数的值,每次操作需要k成本。经过几次操作后(可能是0次)你可以得到另一个数组T。现在给你数组T,问你数组S经过多少次操作可以得到数组T。

题解:

这题当时错了半天,到最后都没a掉,考完看了别人的才a出来,但我感觉我的没有问题。把每个T中每个不存在的数(即T[i]=='0')拿出来单独分析,如果这个数的倍数也不在T中(即T[i*k]=='0')我们就可以认为只需i*k的成本就可以把i、i*2......i*k删除。但此时要注意,如果i*1,i*3不在T中,但是i*2在T中,此时你不能用i*2的成本把i*1,i*3删除,因为你在删除i*1后,i的最小倍数就是i*2,你不能跳过i*2而用i的成本来删除i*3.

代码:

#include "cstdio"
#include "string"
#include"iostream"
#include"algorithm"
#include"queue"
#include"stack"
#include"map"
#include"cmath"

using namespace std;
int a[1000005],vis[1000005];
int main()
{
	int t;
	cin>>t;
	int kk=0;
	while(t--)
	{
		kk++; 
		int n,p=0;
		cin>>n;
		string s;
		cin>>s;
		for(int i=0;i<n;i++)
		{
			vis[i+1]=0;
			if(s[i]=='0')
				a[i+1]=0;
			else
				a[i+1]=1;
		}
	    int sum=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=i;j<=n;j+=i)
			{
				if(a[j]==1)//若该数在T中则跳出循环
					break;
				else if(vis[j]==1)//若该数已被前面使用过,则跳过该数
					continue;
				else
				{
					sum+=i;
					vis[j]=1;
				}
			}
		}
		cout<<sum<<endl;
	} 
	return 0;
}
 

D. Slime Escape

题意:

有n个史莱姆,每个位置为i(1≤i≤n),每个史莱姆有自己的健康值a[i],你当前所在位置为k,史莱姆可以往右或往左走一个位置,每次移动你都要吃掉当前位置上的史莱姆,并获得它的健康值(可能是正也可能是负),吃掉它后,该位置就等于不存在了(如你在6位置,吃掉7后往右再走到达8,此时你的左边应该是5位置,而不是7位置),若你的健康值到达了负值你就直接淘汰了,若你在保证健康值≥0的情况下到达0位置或者n+1位置就算你获胜,问你是否可以获胜。

题解:

考完看大佬代码a的,大佬太强了。先定义i,j代表我们往左和往右走到的位置,我们先往左走,如果往左走可以保证不死并且可以增长健康值,我们就吃掉所走过的这一段的史莱姆,如果保证不死但是健康值不增长我们就跳出,再往右边走,如此反复循环直到i==0或者j==n+1。如果往左走健康值不增长并且往右走健康值也不增长,同时两者都未走到终点,此时就无法获胜了,应当跳出循环(定义一个开关值即可)。

代码:

#include "cstdio"
#include "string"
#include"iostream"
#include"algorithm"
#include"queue"
#include"stack"
#include"map"
#include"cmath"
//#include"bits/stdc++.h"

using namespace std;
int a[200005];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,k;
		cin>>n>>k;
		for(int i=1;i<=n;i++)
			cin>>a[i];
		int i=k-1,j=k+1;
		long long sum=a[k],x=0,y=0;
		while(i>0&&j<=n)
		{
			int k1=1;
			while(i>0&&sum+a[i]+x>=0)
			{
				x+=a[i--];
				if(x>0)
				{
					k1=0;
					sum+=x;
					x=0;
				}
			}
			while(j<=n&&sum+a[j]+y>=0)
			{
				y+=a[j++];
				if(y>0)
				{
					k1=0;
					sum+=y;
					y=0;
				}
			}
			if(k1)
				break;
		}
		if(!i||j==n+1)
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl; 
	} 
	return 0;
}

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会当凌绝顶丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值