CF1189(Div.2)题解(全)

CF1189(Div.2)题解(全)

传送门
在这里插入图片描述
显然不是当场AK,而且D2&E&F都看了题解

PS:如果觉得有帮助,给个赞呗

A. Keanu Reeves

题意:定义0的个数与1的个数不同的01串为"好串".
给你一个长为 n ( 1 ≤ n ≤ 100 ) n(1≤n≤100) n(1n100)的串 s s s,把它分成尽量少的"好串".输出最少分成的段数和这些段.

题解:考虑原串 s s s:

  • s s s是好串:不用分,直接输出
  • s s s非好串:意味着0的个数与1的个数相同.所以串s2…n一定是好串(因为s1要么是0要么是1).又因为s1显然是好串,所以一定可以分为s1和s2…n这两个好串

时间空间显然 O ( n ) O(n) O(n)(但我在比赛时却瞎搞了个 O ( n 2 ) O(n^2) O(n2),太low就只贴 O ( n ) O(n) O(n)代码了)

//Wan Hong 2.2
//notebook
#include<iostream>
#include<cstdio>
#include<cstring>
typedef long long ll;
char a[5011];
int main()
{
   
    ll n,c0=0,c1=0;
    std::cin>>n>>(a+1);
    for(ll i=strlen(a+1);i;--i)
        if(a[i]=='1')++c1;
        else ++c0;
    if(c1!=c0)std::cout<<1<<std::endl<<(a+1);
    else std::cout<<2<<std::endl<<a[1]<<" "<<(a+2);
    return 0;
}

B. Number Circle

题意:给出一个长为 n ( 3 ≤ n ≤ 1 0 5 ) n(3≤n≤10^5) n(3n105)的序列 a 1 , a 2 , a 3 . . . a n ( 1 ≤ a i ≤ 1 0 9 ) a_1,a_2,a_3...a_n(1≤a_i≤10^9) a1,a2,a3...an(1ai109).求能否把这n个数摆成一个圆,使每一个数都严格小于它左右两个数的和.若能,输出"YES",并打印任意一种方案;若不能,输出"NO".
题解:考虑构造.
先把序列排序,使 a i ≤ a j ( 1 ≤ i &lt; j ≤ n ) a_i≤a_{j}(1≤i&lt;j≤n) aiaj(1i<jn)那么,只要将 a i a_i ai a j a_{j} aj摆在一起, a i a_i ai就一定符合要求.
但问题来了, a n a_n an怎么办呢?考虑将 a n a_n an a n − 1 , a n − 2 a_{n-1},a_{n-2} an1,an2摆在一起,如果这样也不行,那么 a n a_n an一定没办法符合要求了(因为 a n , a n − 1 , a n − 2 a_n,a_{n-1},a_{n-2} an,an1,an2是最大的两个)
所以最后的最优序列(之一)就是 a 1 , a 2 . . . a n − 4 , a n − 3 , a n − 2 , a n , a n − 1 a_1,a_2...a_{n-4},a_{n-3},a_{n-2},a_n,a_{n-1} a1,a2...an4,an3,an2,an,an1
(由于是个圆,所以 a 1 a_1 a1 a n − 1 a_{n-1} an1相邻,也是一定合法的)

复杂度瓶颈在于排序, O ( n l o g n ) O(nlogn) O(nlogn).

//Wan Hong 2.2
//notebook
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long ll;//到/**********/之前都是我的板子,之后的代码不再提及
#define INF (1ll<<58)
ll read()//快读,之后不再提及
{
   
	ll x=0,f=1;
	char c;
	do
	{
   
		c=getchar();
		if(c=='-')f=-1;
	}while(c<'0'||c>'9');
	do
	{
   
		x=x*10+c-'0';
		c=getchar();
	}while(c>='0'&&c<='9');
	return f*x;
}
ll min(ll a,ll b)
{
   
	return a<b?a:b;
}
ll max(ll a,ll b)
{
   
	return a>b?a:b;
}

/**********/
#define MAXN 100011
ll a[MAXN];
int main()
{
   
	ll n=read();
	for(ll i=1;i<=n;++i)a[i]=read();
	std::sort(a+1,a+n+1);
	if(a[n]>=a[n-1]+a[n-2])
	{
   
		std::cout<<"NO";
	}
	else
	{
   
		std::cout<<"YES"<<std::endl;
		std::swap(a[n],a[n-1]);
		for(ll i=1;i<=n;++i)std::cout<<a[i]<<" ";
	}
	return 0;
}

C. Candies!

题意:对于一个序列 a 1 , a 2 , a 3 . . . a 2 k a_1,a_2,a_3...a_{2^k} a1,a2,a3...a2k,将 ( a

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值