2021 Niu Guest Winter Holiday Algorithm Basic Training Camp 2 F. Niu Niu and Exchange Sorting (Double-ended Queue Flip)

F. Niu Niu and Exchange Sorting

Title link: https://ac.nowcoder.com/acm/contest/9982/F

Title description:

Niuniu has an array, the array elements are arrays from 1 to n, that is, the value of the array is in the range of 1 to n, and each number only appears once.
Niuniu wants to change the array into ascending order, he can perform the following operations.

First, he must determine a length k, the range of k is between 1 and n.
Next he will perform several operations. In each round of operation, he can select a sub-array of length k, and then perform the interval flip operation.

He can do any number of operations, but he is required to select a sub-array interval that satisfies li ≤ li+1 each time, and the interval length is equal to the k selected at the beginning, which means that once a certain operation selects a certain position of the array Perform the interval reversal operation, and the position of the interval reversal next time will be more to the right than the last time.

Niuniu discovered that there is not always a k that can make the array sorting orderly. Please tell Niuniu whether there is a k that can complete the sorting under the condition of satisfying the rules.

Enter a description:

Enter a positive integer n (1≤n≤10^5) in the first line to indicate the size of the array.
Next, output a row of n positive integers to represent an arrangement, that is, the size of each number ranges from 1 to n and each positive integer only appears once.

Output description:

If there is at least one k that can enable Niuniu to complete the sorting, please output a "yes" in one line, and then start another line to output a k that can satisfy the sorting. The range of k is required to be between [1,n], if there is more Solution, you can output any one.

On the contrary, if there is no k to complete the sorting, please output a "no" directly in one line.

Example 1:

Input
5
5 2 1 4 3
Output
yes
3
Description
First flip the interval [1,3], then flip the interval [3,5]

Example 2:

Input
5
1 2 3 4 5
Output
yes
1
Description
Since it is originally ordered, there is no need to do any operation, so just output a k.

Example 3:

Input
5
5 4 3 2 1
Output
yes
5
Description
Directly flip the [1,5] interval
Remarks:
If there are multiple solutions, you can output any k in the range of [1,n].

Problem-solving ideas:

Since the interval of each flip must be on the right side of the previous time, if you do not flip 1 to the position for the first time, then 1 will not go back. Therefore, the value of k that can be obtained is: the difference between the position of 1 and the value of 1 ( If the 1 is in place, it is the difference between the position of 2 and the difference between the position of i and the position of i ).
Next, consider when you need to flip : when the value of the current position i is not i, consider flipping the interval of length k starting from i, and
then consider under what circumstances there is no solution : the i-th position is not i yet or both are flipped The immovable position is wrong.
You can use an array to simulate whether you want to turn the interval to k, and use a number to mark the order or the reverse order (turn the even number of times or the odd number of times).
When using i-1 to i, first remove i-1 from the leftmost side of the sequence. At this time, it is necessary to judge whether the position of i-1 is correct, and then judge whether the current leftmost i needs to be flipped .

code show as below:

Method 1:

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

struct d{
    
    
	int l,r,flag;
	int qu[200010];
	void reverse(){
    
    
		flag^=1;
	}
	void push_back(int x){
    
    
		if (flag == 0)  qu[r++]=x;
		else qu[--l]=x;
	}
	int front(){
    
    
		if (flag == 0)  return qu[l];
		else return qu[r-1];
	}
	void pop_front(){
    
    
		if (flag == 0)  l++;
		else r--;
	}
}q;
int main(){
    
    
	int n;
	int a[100010];
	int pos[100010];
	cin>>n;
	for (int i=1;i<=n;i++){
    
    
		cin>>a[i];
		pos[a[i]]=i;
	}
	int k=0;
	for (int i=1;i<=n;i++){
    
    
		if(i != pos[i]){
    
    
			k = pos[i]-i+1;
			break;
		}
	}
	if (k==0){
    
    
		cout <<"yes"<<endl<<"1";
		return 0;
	}
	bool ans=1;
	q.l=100000;q.r=100000;
	for (int i=1;i<=k;i++)
		q.push_back(a[i]);
	for (int i=1;i<=n;i++){
    
    
		if (q.front()!=i){
    
    
			q.reverse();
			if (q.front()!=i){
    
    
				ans=0;
				break;
			}
		}
		q.pop_front();
		q.push_back(a[i+k]);
	}
	if (ans) cout <<"yes"<<endl<<k;
	else cout <<"no"<<endl;
	return 0;
}

Method 2:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int a[100010]={
    
    0};
int pos[100010]={
    
    0};
 
int main()
{
    
    
    int n ;
    cin>>n;
    int k=1;
    for(int i=1;i<=n;i++){
    
    
        cin>>a[i];
        pos[a[i]]=i;
    }
    for(int i=1;i<=n;i++){
    
    
        if(i!=pos[i]){
    
    
            k=pos[i]-i+1;
            break;
        }
    }  
    for(int i=1;i<=n;i++){
    
    
        if(a[i]!=i&&i+k-1<=n){
    
    
            for(int j=1;j<=k/2;j++)
            {
    
    
                swap(a[i+j-1],a[i+k-j]);
            }
        }
        if(a[i]!=i){
    
    
            cout<<"no"<<endl;
            return 0;
        }
    }
    cout<<"yes"<<endl;
    cout<<k<<endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_45894701/article/details/113664097