F. Niu Niu e Triagem de Classificação
Link do título: https://ac.nowcoder.com/acm/contest/9982/F
Descrição do título:
Niuniu possui um array, os elementos do array são arrays de 1 a n, ou seja, o valor do array está na faixa de 1 a n, e cada número aparece apenas uma vez.
Niuniu deseja alterar a matriz em ordem crescente, ele pode realizar as seguintes operações.
Primeiro, ele deve determinar um comprimento k, o intervalo de k está entre 1 e n.
Em seguida, ele executará várias operações. Em cada rodada de operação, ele pode selecionar uma submatriz de comprimento k e, em seguida, realizar a operação de inversão de intervalo.
Ele pode fazer qualquer número de operações, mas é necessário selecionar um intervalo de submatriz que satisfaça li ≤ li + 1 a cada vez, e o comprimento do intervalo é igual ao k selecionado no início, o que significa que uma vez determinada operação seleciona uma determinada posição da matriz. Execute a operação de reversão do intervalo e a posição da reversão do intervalo da próxima vez estará mais à direita do que da última vez.
Niuniu descobriu que nem sempre há um k que pode ordenar a classificação do array. Diga a Niuniu se há um k que pode completar a classificação sob a condição de satisfazer as regras.
Insira uma descrição:
Insira um número inteiro positivo n (1≤n≤10 ^ 5) na primeira linha para indicar o tamanho da matriz.
Em seguida, produza uma linha de n inteiros positivos para representar um arranjo, ou seja, o tamanho de cada número varia de 1 a n e cada inteiro positivo aparece apenas uma vez.
Descrição de saída:
Se houver pelo menos um k que pode permitir que Niuniu conclua a classificação, envie um "sim" em uma linha e, em seguida, inicie outra linha para produzir ak que possa satisfazer a classificação. O intervalo de k deve estar entre [ 1, n], se houver mais solução, você pode gerar qualquer uma.
Pelo contrário, se não houver k para completar a classificação, envie um "não" diretamente em uma linha.
Exemplo 1:
Entrada
5
5 2 1 4 3
Saída
sim
3
Descrição
Primeiro inverta o intervalo [1,3] e, em seguida, inverta o intervalo [3,5]
Exemplo 2:
Entrada
5
1 2 3 4 5
Saída
sim
1
Descrição
Como foi pedido originalmente, não há necessidade de fazer nenhuma operação, portanto, apenas envie a k.
Exemplo 3:
Entrada
5
5 4 3 2 1
Saída
sim
5
Descrição
Inverter diretamente o intervalo [1,5]
Observações:
Se houver várias soluções, você pode produzir qualquer k na faixa de [1, n].
Ideias para resolução de problemas:
Uma vez que o intervalo de cada lance deve estar no lado direito da vez anterior, se você não virar 1 para a posição pela primeira vez, então 1 não retrocederá. Portanto, o valor de k que pode ser obtido é: a diferença entre a posição de 1 e o valor de 1 (se o 1 estiver no lugar, é a diferença entre a posição de 2 e a diferença entre a posição de ie a posição de i ).
Em seguida, considere quando você precisa inverter : quando o valor da posição atual i não é i, considere inverter o intervalo de comprimento k começando de i, e
então considere em quais circunstâncias não há solução : a i-ésima posição não é i ainda ou ambos estão invertidos A posição imóvel está errada.
Você pode usar uma matriz para simular se deseja transformar o intervalo em k e usar um número para marcar a ordem ou a ordem inversa (virar o número par de vezes ou o número ímpar de vezes).
Ao usar i-1 para i, primeiro remova i-1 do lado esquerdo da sequência. Neste momento, é necessário julgar se a posição de i-1 está correta e, em seguida, julgar se o i atual mais à esquerda precisa ser invertido .
código mostrado abaixo:
Método 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;
}
Método 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;
}