2021.11.21 JXNU ACS算法组 第四次周赛部分题解

这次出题人整了个全英文的题面,说是为了让我们备考四级,好家伙

Cubes Sorting

描述:

For god's sake, you're boxes with legs! It is literally your only purpose! Walking onto buttons! How can you not do the one thing you were designed for?

Oh, that's funny, is it? Oh it's funny? Because we've been at this for twelve hours and you haven't solved it either, so I don't know why you're laughing. You've got one hour! Solve it!

Wheatley decided to try to make a test chamber. He made a nice test chamber, but there was only one detail absent — cubes.

For completing the chamber Wheatley needs nn cubes. i-th cube has a volume aiai.

Wheatley has to place cubes in such a way that they would be sorted in a non-decreasing order by their volume. Formally, for each i>1, ai−1≤ai must hold.

To achieve his goal, Wheatley can exchange two neighbouring cubes. It means that for any i>1 you can exchange cubes on positions i−1 and i.

But there is a problem: Wheatley is very impatient. If Wheatley needs more than n⋅(n−1)/2−1 exchange operations, he won't do this boring work.

Wheatly wants to know: can cubes be sorted under this conditions?

输入:

Each test contains multiple test cases.

The first line contains one positive integer t (1≤t≤1000), denoting the number of test cases. Description of the test cases follows.

The first line of each test case contains one positive integer n (2≤n≤5⋅10^4) — number of cubes.

The second line contains n positive integers ai (1≤ai≤10^9) — volumes of cubes.

It is guaranteed that the sum of n over all test cases does not exceed 10^5.

输出:

For each test case, print a word in a single line: "YES" (without quotation marks) if the cubes can be sorted and "NO" (without quotation marks) otherwise.

样例输入:

3
5
5 3 2 1 4
6
2 2 2 2 2 2
2
2 1

样例输出:

YES
YES
NO

注释:

In the first test case it is possible to sort all the cubes in 7 exchanges.

In the second test case the cubes are already sorted.

In the third test case we can make 0 exchanges, but the cubes are not sorted yet, so the answer is "NO".

题目分析:

这道题的大致意思是,给我们一个数组,问是否能在 n * (n-1) / 2 - 1 次操作内完成相邻两个数组交换位置并使最后数组呈递增。

解题思路:

其实这不就是冒泡排序吗,每次都比较相邻的两个数,但是数据量太大,不可能直接模拟,我们要找到冒泡排序的规律,他最大能接受的次数是 n * (n-1) / 2 - 1 为什么还 -1 呢?我们仔细想,如果最坏的情况冒泡排序是 (n-1)+(n-2)+(n-3)+...+1 也就是 n-1 项叠加,这不就是 n * (n-1) / 2 吗,所以他不能接受的只有最坏情况,如果中间有不变的就可以直接输出了(因为一定满足)

代码示例:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;

int t,n;
int a[1001000];
bool book;

int main(){
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=1;i<n;i++){
			if(a[i]<=a[i+1]){
				book=1;
				break;
			}
		}
		if(book==1) cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
		book=0;
	}
	return 0;
}


C Trouble Sort

描述:

Ashish has n elements arranged in a line.

These elements are represented by two integers ai — the value of the element and bi — the type of the element (there are only two possible types: 0 and 1). He wants to sort the elements in non-decreasing values of ai.

He can perform the following operation any number of times:

  • Select any two elements i and j such that bi≠bj and swap them. That is, he can only swap two elements of different types in one move.

Tell him if he can sort the elements in non-decreasing values of ai after performing any number of operations.

输入:

The first line contains one integer t (1≤t≤100) — the number of test cases. The description of the test cases follows.

The first line of each test case contains one integer n (1≤n≤500) — the size of the arrays.

The second line contains nn integers ai (1≤ai≤105)  — the value of the ii-th element.

The third line containts nn integers bi (bi∈{0,1})  — the type of the ii-th element.

输出:

For each test case, print "Yes" or "No" (without quotes) depending on whether it is possible to sort elements in non-decreasing order of their value.

You may print each letter in any case (upper or lower).

样例输入:

5
4
10 20 20 30
0 1 0 1
3
3 1 2
0 1 1
4
2 2 4 8
1 1 1 1
3
5 15 4
0 0 0
4
20 10 100 50
1 0 0 1

样例输出:

Yes
Yes
Yes
No
Yes

注释:

For the first case: The elements are already in sorted order.

For the second case: Ashish may first swap elements at positions 1 and 2, then swap elements at positions 2 and 3.

For the third case: The elements are already in sorted order.

For the fourth case: No swap operations may be performed as there is no pair of elements i and j such that bi≠bj. The elements cannot be sorted.

For the fifth case: Ashish may swap elements at positions 3 and 4, then elements at positions 1 and 2.

题目分析:

有两行,一行是这个数组存的数值,另一行存储的是元素的类型,每次交换只能和不同类型的操作,问最后是否能调整成一个有非递减的序列,当我说完大意的时候,其实有的人已经有想法了,这就是个脑筋急转弯

解题思路:

你想你有一个数组,其中有很多数值可以随便插入一个位置,只要他们类型不同,那你只要有一个不一样类型的数值,那就一定可以排成非递减的序列,什么你问我为什么?

我们可以把这个过程简化一下,只有一个不同类型的数值,我们把它当作基准值并排到首位,然后每次查找后面数组中比它小最多的数值排到前面,到了最后发现后面都比它大,我们可以再翻过来把没排过序的部分数组进行类似排序,最后找到基准位置就可以了,更多的不同类型是相似的操作过程这里不再赘述。

代码示例:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int t;
int n;

struct number{
	int value;
	int type;
}a[100010];

int main(){
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i].value;
		for(int i=1;i<=n;i++) cin>>a[i].type;
		bool ok=0;
		for(int i=1;i<n;i++) if(a[i+1].type!=a[i].type) ok=1;
		if(ok==0){
			bool book=0;
			for(int i=1;i<n;i++){
				if(a[i].value>a[i+1].value){
					cout<<"No"<<endl;
					book=1;
					break;
				}
			}
			if(book==0) cout<<"Yes"<<endl;
		}
		else cout<<"Yes"<<endl;
		memset(a,0,sizeof(a));
	}
}


F Sort the Array

描述:

Being a programmer, you like arrays a lot. For your birthday, your friends have given you an array a consisting of n distinct integers.

Unfortunately, the size of a is too small. You want a bigger array! Your friends agree to give you a bigger array, but only if you are able to answer the following question correctly: is it possible to sort the array a (in increasing order) by reversing exactly one segment of a? See definitions of segment and reversing in the notes.

输入:

The first line of the input contains an integer n (1 ≤ n ≤ 105) — the size of array a.

The second line contains n distinct space-separated integers: a[1], a[2], ..., a[n] (1 ≤ a[i] ≤ 109).

输出:

Print "yes" or "no" (without quotes), depending on the answer.

If your answer is "yes", then also print two space-separated integers denoting start and end (start must not be greater than end) indices of the segment to be reversed. If there are multiple ways of selecting these indices, print any of them.

样例输入:

3
3 2 1

样例输出:

yes
1 3

样例输入:

4
2 1 3 4

样例输出:

yes
1 2

样例输入:

4
3 1 2 4

样例输出:

no

样例输入:

2
1 2

样例输出:

yes
1 1

注释:

Sample 1. You can reverse the entire array to get [1, 2, 3], which is sorted.

Sample 3. No segment can be reversed such that the array will be sorted.

Definitions

A segment [l, r] of array a is the sequence a[l], a[l + 1], ..., a[r].

If you have an array a of size n and you reverse its segment [l, r], the array will become:

a[1], a[2], ..., a[l - 2], a[l - 1], a[r], a[r - 1], ..., a[l + 1], a[l], a[r + 1], a[r + 2], ...,

题目分析:

题目简单来说就是,给你一个序列,问是否能通过旋转中间一个区间,变成递增的序列。

解题思路:

也就是我们要在所有区间里找到一个翻转后能实现递增的子区间(有可能是他自己),但是观察数据我们可以发现,他的数据量很大,基本上就排一次序就满了(而且是快排)。对此我们想,如果排完序后,就会改变他原本数字的位置,所以我们可以记录原本数字的位置,再比较改变后,是否发生了区间的翻转,而想证明区间翻转本质上就是找逆序对,所以我们就有思路了,找到翻转区间,另外来一次循环判断这之间是否成逆序排列,是就yes,否就no

代码示例:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int n;
int ansl,ansr;
int z[1000100];

struct number{
	int pos;
	int num;
}a[1000100];

bool cmp(number x,number y){
	return x.num<y.num;
}

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].num;
		a[i].pos=i;
	}
	sort(a+1,a+1+n,cmp);
	int l=-1,r=-1;
	for(int i=1;i<=n;i++){
		if(a[i].pos!=i){
			l=i;
			break;
		}
	}
	if(l==-1){
		cout<<"yes"<<endl;
		cout<<"1 1"<<endl;
		return 0;
	} 
	for(int j=n;j>=l;j--){
		if(a[j].pos!=j){
			r=j;
			break;
		}
	}
	ansl=l,ansr=r;
	for(int i=l;i<=ansr;i++){
		if(a[i].pos!=r){
			cout<<"no"<<endl;	
			return 0;
		} 
		r--;
	}
	cout<<"yes"<<endl;
	cout<<ansl<<" "<<ansr<<endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值