Codeforces Round #622 (Div. 2)

Codeforces Round #622 (Div. 2)

A. Fast Food Restaurant

题意

有三种食物,每个客人每样最多拿一个,每个客人拿的组合不能相同,问最多能供应多少个客人

题解

每样最多拿一个,一共有7种取法: a , b , c , a b , a c , b c , a b c a,b,c,ab,ac,bc,abc a,b,c,ab,ac,bc,abc,用7个if判断一下就好了

代码

#include<iostream>
#include<cstdio>
using namespace std;
 
int main()
{	long _,x,y,z,i,ans;
	for(scanf("%ld",&_);_;_--){
		scanf("%ld%ld%ld",&x,&y,&z);
		if(x<y)swap(x,y);
		if(x<z)swap(x,z);
		if(y<z)swap(y,z);
		ans=0;
		if(x>=1){x--;ans++;}
		if(y>=1){y--;ans++;}
		if(z>=1){z--;ans++;}
		if(x>=1&&y>=1){x--;y--;ans++;}
		if(z>=1&&y>=1){z--;y--;ans++;}
		if(x>=1&&z>=1){x--;z--;ans++;}
		if(x>=1&&y>=1&&z>=1){x--;y--;z--;ans++;}
		printf("%ld\n",ans);
	}
	return 0;
}

B. Different Rules

题意

定义一种新的最终排名的方法,使用两场比赛的排名相加得到最终分数,再按照这个分数重新排名得到最终排名(两场比赛中没有并列排名),给出某人的两场比赛排名 x x x y y y,求可能的最大最小最终排名

题解

因为总人数 n n n的范围超级大 [ 1 , 1 0 9 ] [1,10^9] [1,109],所以必须是结论题。
首先是最小排名,分两种情况:
1) x + y ⩽ n + 1 x+y \leqslant n+1 x+yn+1
在这里插入图片描述
最优情况如图所示,排名为1

2) x + y > n + 1 & & y ≠ n x+y > n+1 \&\& y \not= n x+y>n+1&&y=n
在这里插入图片描述
如图,绿色和红色的匹配方式不变,但是个数变了,这时前面,黄色便是能超过自己的人, N − ( N − Y − 1 ) − ( N − X − 1 ) − 2 = X + Y − N N-(N-Y-1)-(N-X-1)-2=X+Y-N N(NY1)(NX1)2=X+YN,然后+1就是最小排名了

综上,最小排名就是 m a x ( 1 , x + y − n + 1 ) max(1,x+y-n+1) max(1,x+yn+1)

接下来看最大排名,因为相等也算输,所以尽量构造相等的就好了
在这里插入图片描述
由图可知,理想状态下答案就是 m i n ( n , x + y − 1 ) min(n,x+y-1) min(n,x+y1)

代码

#include<iostream>
#include<cstdio>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
using namespace std;

int main()
{	long _,n,x,y;
	for(scanf("%ld",&_);_;_--){
		scanf("%ld%ld%ld",&n,&x,&y);
		printf("%ld %ld\n",max(1,min(n,x+y-n+1)),max(1,min(n,x+y-1)));
	}
	return 0;
}

C2. Skyscrapers (hard version)

题意

建设大楼,要求每栋楼有限高,而且不允许存在一栋楼两边都有比他更高的楼,要求建成的楼总高度最大
ps:C1跟C2题目一样的,就不放了

题解

(按照思维上的难度,这题比B简单,题目安排的锅。。)
因为任何一栋楼都要满足题目的限制,所以可以任找一栋楼来作为起点来找规律。
对于找到的楼,向一个方向拓展时,如果是向低处的,那么这个方向上所有楼都得满足不上升,反之亦然。
由此可知,我们只需要找到一个“最高点”,向左向右全部向低处拓展就好了。
至于这个最高点,可以用dp预处理两个数组 l l l r r r,分别是从左向右和从右向左一路不下降高度建楼得到的总高度,最后得到的 l [ i ] + r [ i + 1 ] l[i]+r[i+1] l[i]+r[i+1]的最大值所在点就是“最高点”了

代码

#include<iostream>
#include<cstdio>
#include<stack>
#define min(a,b) (((a)<(b))?(a):(b))
#define ll long long
#define def 500010
using namespace std;

stack<ll>sta;
ll a[def],l[def],r[def];

int main()
{	ll n,i,maxx,minn;
	scanf("%lld",&n);
	for(i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	for(i=1;i<=n;i++){
		while(!sta.empty()&&a[i]<a[sta.top()])
			sta.pop();
		if(sta.empty())
			l[i]=i*a[i];
		else
			l[i]=(i-sta.top())*a[i]+l[sta.top()];
		sta.push(i);
	}
	while(!sta.empty())sta.pop();
	for(i=n;i>=1;i--){
		while(!sta.empty()&&a[i]<a[sta.top()])
			sta.pop();
		if(sta.empty())
			r[i]=(n-i+1)*a[i];
		else
			r[i]=(sta.top()-i)*a[i]+r[sta.top()];
		sta.push(i);
	}
	maxx=1;
	for(i=1;i<n;i++)
		if(l[i]+r[i+1]>l[maxx]+r[maxx+1])
			maxx=i;
	minn=a[maxx];
	for(i=maxx;i>=1;i--){
		minn=min(minn,a[i]);
		a[i]=minn;
	}
	minn=a[maxx+1];
	for(i=maxx+1;i<=n;i++){
		minn=min(minn,a[i]);
		a[i]=minn;
	}
	for(i=1;i<=n;i++)
		printf("%lld ",a[i]);
	printf("\n");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值