Codeforces Round #771 (Div. 2)(A~C)

这次的cf也就能写出A~C,B题挂了,所以补一下


本来只有B题,但还是把A和C的代码搬上来吧,简单解释

A:

https://codeforces.com/contest/1638/problem/A

题意:

给定长度为n的数组

可进行一次或0次操作:选定l和r(1 <= l,r <= n),逆序位置l到r的所有数组元素

输出进行操作后字典序最小的数组

分析:

最小的当然是1234567.....

当然不可能每次都能成这样,越高位决定权越大嘛,所以找到第一个与数位不对应的位置i作为l,数字i所在的位置作为r,逆序l到r的数组元素,然后输出就可以了,这道题我的代码很繁琐,不建议学习.......

比如用用continue;别if-else,先逆序再输出逻辑跟清晰等等

AC Code:

#include<bits/stdc++.h>
using namespace std;
int t,n;
int a[510];
void solve()
{
	int l,r;
	l = r = 0;
	cin >>n;
	for(int i = 1; i <= n; i++){
		cin >>a[i];
		if(a[i] != i && l == 0) l = i;
		if(l != 0 && a[i] == l) r = i;
	}
	if(l == 0){
	 
		for(int i = 1; i <= n; i++){
			cout <<a[i];
			if(i != n) cout <<" ";
		}
	}
	else{
		if(l != 1)
		for(int i = 1; i < l; i++){
			cout <<a[i];
			cout <<" ";
		}
		for(int i = r; i >= l; i--){
			cout <<a[i];
			cout <<" ";
			
		}
		if(r != n)
		for(int i = r+1; i <= n; i++){
			cout <<a[i];
			cout <<" ";
		}
	}
	cout <<endl;
}
int main(void)
{
	cin >>t;
	while(t--)
	{
		solve();	
	}
	return 0;
} 

 B:https://codeforces.com/contest/1638/problem/B

题意:

给定长度为n的数组

可进行的操作:如果a[i]+a[i+1] (1 <= i <= n)是一个奇数,你可以swap(a[i],a[i+1])

现在问你能不能通过这个操作(不限次数)将原数组变为一个完全升序的数组

分析:

这题挂了

第一眼看到,这不就是加了个条件的冒泡排序么,然后就这样写了,预测试就过了,但没想到总共8组数据,昨天晚上只测四组。。。。。

接下来分析:

奇偶性相同的数相加一定是偶数

也就是说在数组的奇数元素子序列和偶数元素子序列里,元素的相对位置是不可改变的,至于偶数和奇数之间,哪怕大小位置不对,都是可调的。

所以思路也就是检验数组的奇数元素子序列和偶数元素子序列原本是不是有序的

AC Code:

#include<bits/stdc++.h>
using namespace std;
int t,n,x;
void solve()
{
	bool ans = true;
	cin >>n;
	int ji,ou;
	ji = ou = -1;
	for(int i = 1; i <= n; i++){
		cin >>x;
		if(x & 1){
			if(x < ji) ans = false;
			else ji = x;
		}
		else{
			if(x < ou) ans = false;
			else ou = x;
		} 
	} 
	if(ans) cout <<"YES" <<endl;
	else cout <<"NO" <<endl;
}
int main(void)
{
	std::ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin >>t;
	while(t--) solve();	
	return 0;
} 

不得不说这题有去年ICPC南京站的C题感觉了


C:  http://​https://codeforces.com/contest/1638/problem/C​

题意:

一个点数为n的无向图,无向图中的元素为1-n,有i,j,如果出现i < j && a[i] > a[j],则位置i和j之间出现一条边,问你这个无向图有多少个连通块

分析:

其实描述成数组更好理解,又有冒泡排序的意味了。

如果前x个元素是1~x的全排列,那这些元素就不会与后面的元素产生联系,就会出现一个连通块,就这样,注意好维护就行了,别又搞成n^2

AC Code:

#include <bits/stdc++.h>
using namespace std;
int t,n,x;
bool a[100010];
void solve()
{
	memset(a,false,sizeof(a));
	int res = 0,cnt = 0;
    //cnt用来记录读入数据后是前多少的全排列
	cin >>n;
	for(int i = 1; i <= n; i++){
		cin >>x; a[x] = true;
        //如果是前i的全排列,连通块加一 
		if(x == cnt+1) cnt++;
		while(a[cnt+1]) cnt++;
		if(cnt == i)res++;
	}
	cout <<res <<endl;
}
int main(void)
{
	std::ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin >>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UmVfX1BvaW50

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值