Codeforces Deltix Round Summer 2021 [Div.1 + Div.2]个人题解

Codeforces Deltix Round Summer 2021 [Div.1 + Div.2]个人题解

比赛链接:Codeforces Deltix Round Summer 2021 [Div.1 + Div.2]

A题 A Variety of Operations

题目大意:

给你两个数 \(a\)\(b\) ,初始值都为 \(0\),你有三种操作:\(1.(a+k,b+k)\) \(2.(a+k,b-k)\) \(3.(a-k,b+k)\)
给出 \(c,d\) 问最少的操作次数使 \(a=c\)\(b=d\)

思路解析:

我们可以直观地发现三种操作是不会改变 \(a-b\) 的奇偶性的,所以如果 \(c-d\) 为奇数的话就一定不可能有可行方案的。

如果 \(a-b\) 为偶数的话,我们可以发现我们可以用不超过 \(2\) 次操作使它由 \(a,b\)\(c,d\) ,第一步 \((a+(a+b)/2,b+(a+b)/2)\) ,第二步 \((a+(a-b)/2,b-(a-b)/2)\)\((a-(a-b)/2,b+(a-b)/2)\)

特别的有两种特殊情况需要考虑,如果 \(c,d\) 都为 \(0\) 的时候,不需要进行任何操作,如果 \(c=d\) 的时候,我们只需进行一次操作一即可

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;

int main(){

	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);

	int t;
	cin>>t;
	while(t--){
		int  n,m;
		cin>>n>>m;

		if(n==0&&m==0){
			cout<<0<<endl;
			continue;
		}

		if((abs(n-m))%2==1)cout<<-1<<endl;
		else if(n==m)cout<<1<<endl;
		else cout<<2<<endl;
	}

}

B题 Take Your Places!

题目大意:

给出一数组,你可以每次交换相邻的两个元素,问最少多少次能够把数组变成奇偶相间,如果不能输出 \(-1\)

思路解析:

首先我们考虑不能的情况:很显然,如果 \(abs(奇数数量-偶数数量)> 1\) 一定不能

如果可行的话,怎样使次数最少呢?

我们可以把交换次数理解为当前元素与它目标位置的距离,因为我们可以通过他们之间距离次交换来交换任意两个元素的位置,所以我们只要把应该交换的元素移到他最近的目标位置即可。

我们可以这样考虑,什么情况下满足最终的要求,只有两种情况:奇偶奇偶奇偶... 或者 偶奇偶奇偶奇...
所以我们就可以单独存储奇数和偶数,按下标大小从小到大,一一对应目标位置的奇偶,答案就只需累加他与目标位置之间的距离即可,当然还需要取 \(min\)

其实,如果 \(abs(奇数数量-偶数数量) = 1\) 的话,可以发现他的目标位置是唯一的

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;

ll a[maxn],pos[maxn],top;
ll pos2[maxn];
ll sum,tot;

int main(){

	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);

	int t;
	cin>>t;
	while(t--){
		tot=0;
		sum=0;
		ll n;
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			if(a[i]%2==0)pos[++sum]=i;
			else pos2[++tot]=i;
		}
		if(abs(tot-sum)>1)cout<<-1<<endl;
		else {
			ll ans=0,ans2=0;
			ll now=1;
			for(int i=1;i<=sum;i++){
				if(pos[i]!=now)ans+=abs(now-pos[i]);
				now+=2;
			}
			now=1;
			for(int i=1;i<=tot;i++){
				if(pos2[i]!=now)ans2+=abs(now-pos2[i]);
				now+=2;
			}
			if(sum==tot)cout<<min(ans,ans2)<<endl;
			else if(sum>tot)cout<<ans<<endl;
			else cout<<ans2<<endl;
		}
	}
}

C题 Compressed Bracket Sequence

题目大意:

给你一个括号字符串的映射数组 \(a\) ,奇数位表示左括号的数量,偶数位表示右括号的数量,这样形成了一个长度为 \(\sum a_i\) 的括号字符串,问有多少合法括号序列子串

思路解析:

AC代码:

Codeforces Deltix Round Summer 2021 [Div.1 + Div.2]个人题解

上一篇:修改原查询与利用查询创建新查询


下一篇:【非加密教程】qt creator项目打包 单exe文件