Codeforces Round #637 (Div. 2)题解+总结

题目链接

A - Nastya and Rice

题目大意:每个物品质量范围在 a − b a-b ab a + b a+b a+b内,你需要判断n个物品总质量范围在不在 c − d c-d cd c + d c+d c+d内。

题解:其实就是判断两个区间是否相交,分三种情况讨论即可。(我做的时候一直少考虑一种情况,白给了三发)

代码

#include <bits/stdc++.h>
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<<a<<endl;
#define exp 0.000001
#define pb push_back
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
 
 
 
void solve()
{
int n;
scanf("%d",&n);
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
int temp1=(a-b)*n;
int temp2=(a+b)*n;
if((temp1>=c-d&&temp1<=c+d)||(temp2>=c-d&&temp2<=c+d)||(temp1<=c-d&&temp2>=c+d)){
printf("Yes\n");
return ;
}
printf("No\n");
}
int main()
{
    int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

B - Nastya and Door

题目大意:给你一个数组,当 a i > = a i − 1 a_i>=a_{i-1} ai>=ai1 a i > = a i + 1 a_i>=a_{i+1} ai>=ai+1时,称 a i a_i ai为数组的峰,让你求长度为k的连续段中的峰的最大值(首尾不算峰)。

题解:先预处理出所有峰,然后从左向右依次遍历。时间复杂度O(n)。

代码

#include <bits/stdc++.h>
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<<a<<endl;
#define exp 0.000001
#define pb push_back
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
 
 
int a[maxn];
int vis[maxn];
void solve()
{
int k,n;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
vis[i]=0;
}
for(int i=2;i<n;i++)
if(a[i]>a[i-1]&&a[i]>a[i+1])
	vis[i]=1;
int l=1,p=0;
for(int i=1;i<k;i++)
{
if(vis[i])
	p++;
}
int ll=1,rr=k;
int temp=p;
while(rr<n)
{
if(vis[ll+1])
	temp--;
if(vis[rr])
	temp++;
ll++;
rr++;
if(temp>p)
{
	p=temp;
	l=ll;
}
}
p++;
printf("%d %d\n",p,l);
}
int main()
{
    int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

C. Nastya and Strange Generator

题目大意:题目定了两个数列, r i r_i ri表示从 i i i~ n n n第一个还没被放置的数字。 c o u n t i count_i counti表示数列 r r r i i i的个数。并规定每一次只能放置count中最大所对应的下标。给你一种放置方案问你是否符合。

题解:很明显刚开始 c o u n t count count数列全为 1 1 1,如果我们放置最后一个数字,则依然全为 1 1 1。如果我们放置之前的任一数字,我们就不得不从这个数字开始按顺序放到最大。按照上述放置方法模拟就好。

代码

#include <bits/stdc++.h>
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<<a<<endl;
#define exp 0.000001
#define pb push_back
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
 
 
int a[maxn];
void solve()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
	scanf("%d",&a[i]);
}
int cnt=1;
int temp=n;
while(cnt<=n)
{
if(a[cnt]==temp)
{
	temp--;
	cnt++;
}
else {
	int i;
for(i=cnt+1;;i++)
{
	
	if(a[i]!=a[i-1]+1)
	{
		printf("NO\n");
		//test(i);
		return ;
	}
	if(a[i]==temp)
		break;
}
temp=a[cnt]-1;
cnt=i+1;
}
}
printf("YES\n");
}
int main()
{
    int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

D - Nastya and Scoreboard

题目大意:有 n n n个计分数字从左到右显示数字,每个数字有 7 7 7个二极管,但是这些二极管有k个不亮了。他问你原本计分板上的数字最大可能是多少。

题解:题目可以等价于点亮 k k k个二极管所能现实的最大数字。先预处理出每一位补全到各个数字需要点亮的二极管的数目,如果不行置为 − 1 -1 1。题目的难点就在于要正好点亮 k k k个二极管(不能多也不能少)。我们只需要对所需的二极管数目求一个后缀和并压入到一个集合中去重(超过 k k k直接舍去),从左到右并对于每一位从大到小进行枚举。

代码

#include <bits/stdc++.h>
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<<a<<endl;
#define exp 0.000001
#define pb push_back
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
 
 
string s[2005];
string ck[10]={"1110111","0010010","1011101","1011011","0111010","1101011","1101111","1010010","1111111","1111011"};
set<int> si[2005];
int vi[2005][10];
int ans[2005];
void solve()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
	cin>>s[i];
mem(vi,-1);
for(int i=1;i<=n;i++)
   si[i].clear();
si[n+1].insert(0);
for(int i=n;i>=1;i--)
{
	 for(int j=0;j<=9;j++)
	 {
	 	int cnt=0,flag=1;
	 	for(int k=0;k<=6;k++)
	 	{
	 		if(s[i][k]=='1'&&ck[j][k]=='0')
	 		{
	 			flag=0;
	 			break;
	 		}
	 		else if(s[i][k]=='0'&&ck[j][k]=='1')
	 			cnt++;
	 	}
	 	if(flag)
        vi[i][j]=cnt;
	 }
	 for(int j=0;j<=9;j++)
	 {
	 	if(vi[i][j]!=-1)
	 	{   
	 		 set<int>::iterator it;
	 		 for(it=si[i+1].begin();it!=si[i+1].end();it++)
	 		 {
	 		 	if(*it+vi[i][j]<=k)
	 		 	si[i].insert(*it+vi[i][j]);
	 		 }
	 	}
	 }
}
for(int i=1;i<=n;i++)
{
	int j;
	for(j=9;j>=0;j--)
	{
		if(vi[i][j]!=-1&&si[i+1].count(k-vi[i][j]))
		{
			ans[i]=j+'0';
			k-=vi[i][j];
			break;
		}
	}
	if(j==-1)
	{
		printf("-1\n");
		return ;
	}
}
for(int i=1;i<=n;i++){
if(i==n)
printf("%c\n",ans[i]);
else printf("%c",ans[i]);
}
}
int main()
{
    //int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值