CodeTON Round 8 (Div. 1 + Div. 2, Rated, Prizes!)

文章讨论了三个编程题目,涉及如何构造满足特定条件的数组(使得部分元素按升序排列)、生成满足MEX性质的排列,以及在正多边形中通过选择顶点切出不相交对角线形成三角形的数量计算。
摘要由CSDN通过智能技术生成

A. Farmer John’s Challenge

构造一个长度为n的数组a
满足循环右移数组中恰好有k个是升序的

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
int n,k;
void solve() {
	cin>>n>>k;
	if(k==1){
		for(int i=1;i<=n;i++) cout<<i<<' ';
		cout<<endl;
	}
	else if(n==k){
		for(int i=1;i<=n;i++) cout<<1<<' ';
		cout<<endl;
	}
	else{
		cout<<-1<<endl;
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

B. Bessie and MEX

长度为n的数组a(数[-n,n])

构造一个长度为n的排列p,使得ai=mex(p1,p2,…pi)-pi
一定有解

首先,如果a1为负数x的话,那么p1为-x
如果a1为1的话,那么p1为0

维护mex,也就是缺mex这个数
如果令pi为mex的话,那么结果是mex+1-mex=1
否则,令pi为x,则mex-x=a[i]==>x=mex-a[i]
不对

应该倒着推,mex(p1,p2,p3,…pn)=n,所以n-p[n]=a[n]>p[n]=n-a[n]
然后求出倒数第二个mex,以此类推,mex-p[i]=a[i]
>p[i]=mex-a[i]

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int N=2e5+10;
int a[N];
int p[N];
int n;
void solve() {
	cin>>n;
	set<int>s;
	for(int i=1;i<=n;i++) cin>>a[i];
	p[n]=n-a[n];
	s.insert(p[n]);
	for(int i=n-1;i>=1;i--){
		p[i]=*s.begin()-a[i];
		s.insert(p[i]);
	}
	for(int i=1;i<=n;i++) cout<<p[i]<<' ';
	cout<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

C1. Bessie’s Birthday Cake (Easy Version)

边长为n的正多边形,顶点按照顺时针方向从1到n

贝西选择了x个顶点,以及还可以选择其它顶点最多y个(easy版本y为0)
然后切出不相交的对角线,问最多切成几个三角形

问分成几块问题,往往是通过数线产生的交点个数或者有效点的个数
问切成几个三角形,答案为有效的个数-2
如果两个有效点之间恰好有1个点,那么中间的那个点也是有效点

1 2 3 4 5 >2个
1 2 3
>1个
1 2 3 4 5 6==>3个

trick:

问分成几块问题,往往是通过数线产生的交点个数或者有效点的个数

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
int n,x,y;
void solve() {
	cin>>n>>x>>y;
	vector<int>res;
	for(int i=0;i<x;i++){
		int d;
		cin>>d;
		res.push_back(d);
	}
	int ans=x;
	sort(res.begin(),res.end());
	for(int i=1;i<(int)res.size();i++){
		if(res[i]==res[i-1]+2) ans++;
	}
	int len=res.size();
	int a=res[len-1]+2;
	if(a>n) a-=n;
	if(a==res[0]) ans++;
	cout<<ans-2<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

C2. Bessie’s Birthday Cake (Hard Version)

如果两个有效的点之间的个数为奇数,记为cnt,那么只需要(cnt-1)/2个点就可以产生cnt个有效点,如果为偶数的话,那么需要cnt/2个点产生cnt个有效点

所以优先奇数

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
int n,x,y;
void solve() {
	cin>>n>>x>>y;
	vector<int>res;
	for(int i=0;i<x;i++){
		int d;
		cin>>d;
		res.push_back(d);
	}
	int ans=x;
	int len=res.size();
	sort(res.begin(),res.end());
	vector<int>ji,ou;
	int l=res[0]+n-res[len-1]-1;
	if(l%2&&l) ji.push_back(l);
	else ou.push_back(l);
	for(int i=1;i<len;i++){
		int l=res[i]-res[i-1]-1;
		if(l%2) ji.push_back(l);
		else ou.push_back(l);
	}
	sort(ji.begin(),ji.end());
	sort(ou.begin(),ou.end());
	for(int i=0;i<(int)ji.size();i++){
		if(ji[i]/2<=y){
			ans+=ji[i];
			y-=ji[i]/2;
		}
		else {
			ans+=y*2;
			y=0;
			break;
		}
	}
	for(int i=0;i<(int)ou.size();i++){
		if(ou[i]/2<=y){
			ans+=ou[i];
			y-=ou[i]/2;
		}
		else{
			ans+=y*2;
			y=0;
			break;
		}
	}
	cout<<ans-2<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值