1455 D. Sequence and Swaps(思维)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1455 D. Sequence and Swaps(思维)相关的知识,希望对你有一定的参考价值。

LINK

考虑枚举以 i i i位置作为开头而 j j j位置作为结尾位置,可以得到最后排序后的数组

那么扫描所有 a k ! = b k a_k!=b_k ak!=bk的索引 k k k

如果此时 a k < b k a_k<b_k ak<bk是无解的,因为交换操作只能让数字变小

如果此时 a k = = b k a_k==b_k ak==bk,不需要管

如果此时 a k > b k a_k>b_k ak>bk,需要把 a k a_k ak加入操作队列,且此时的操作前驱是数字 b i b_i bi对应的索引位置

但是此时的复杂度比较劣,为 O ( n 3 l o g ( n ) ) O(n^3log(n)) O(n3log(n))

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10;
int a[maxn],b[maxn],n,ans,x;
int main()
{
	ios::sync_with_stdio( false ); cin.tie( 0 ); cout.tie( 0 );
	int t; cin >> t;
	while( t-- )
	{
		cin >> n >> x;
		int ans = 1e9, flag = 1;
		for(int i=1;i<=n;i++)
		{
			cin >> a[i];
			if( a[i]<a[i-1] )	flag = 0;
		}
		if( flag )	ans = 0;
		for(int i=1;i<=n;i++)
		{
			if( a[i]<=x )	continue;
			for(int j=1;j<=n;j++)
			{
				if( a[j]<a[i] )	continue;
				for(int q=1;q<=n;q++)	b[q] = a[q];
				b[j] = x;
				sort( b+1,b+1+n );
				int res = 0;
				vector<int>v1,v2;
				for(int q=1;q<=n;q++)
				{
					if( a[q]==b[q] )	continue;
					res++;//为了把b[q]换过来 
					if( a[q]<b[q] )	{ res = 1e9; break; }
					v1.push_back( a[q] ); v2.push_back( b[q] );
				}
				if( res>=1e9 )	break;
				sort( v1.begin(),v1.end() ); sort( v2.begin(),v2.end() );
				for(int i=0;i<v1.size()-1;i++)
					if( v1[i]!=v2[i+1] )	res = 1e9;
				if( v1[v1.size()-1]!=a[j] )	res = 1e9;
				if( v2[0]!=x )	res = 1e9;
				ans = min( ans,res );
			}
		}
		if( ans>n )	ans = -1;
		cout << ans << endl;
	}
}

正解

正解就比较巧妙了emm

由于操作的实质,是选择一个递增的序列,整体往右移一个距离,且第一个位置变成 x x x

也就是 a x 1 , a x 2 . . . a x k = = > x , a x 1 . . . . a x k − 1 a_{x_1},a_{x_2}...a_{x_k} ==> x,a_{x_1}....a_{x_{k-1}} ax1,ax2...axk==>x,ax1....axk1,整体减小

所以选定的索引满足 x < a x 1 < a x 2 . . . < a x k x<a_{x_1}<a_{x_2}...<a_{x_k} x<ax1<ax2...<axk,交换并不会改变相对大小,所以需要满足

x 1 < x 2 < x 3 . . . < x k x_1<x_2<x_3...<x_k x1<x2<x3...<xk

所以操作一定是从前往后的(如果这都不能有序就无解)

注意到若存在 a i > x & & a j > x & & i < j a_i>x\\&\\&a_j>x\\&\\&i<j ai>x&&aj>x&&i<j

如果 a i a_i ai不与 x x x交换,那么 a j a_j aj也不会和 x x x交换

如果 a j a_j aj坚持和 x x x交换,此时 a j = x < a i a_j=x<a_i aj=x<ai不满足升序

所以只需要从前往后扫描,每次先检查数组是否已经有序,有的话就退出输出答案

否则检查当前 a i a_i ai是否大于 x x x,如果大于就交换

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10;
int a[maxn],b[maxn],n,ans,x;
int main()
{
	ios::sync_with_stdio( false ); cin.tie( 0 ); cout.tie( 0 );
	int t; cin >> t;
	while( t-- )
	{
		cin >> n >> x;
		for(int i=1;i<=n;i++)	cin >> a[i];
		int las = n;
		for(int i=n-1;i>=1;i--)
		{
			if( a[i]<=a[i+1] )	las = i;
			else	break;
		}
		int ans = 0;
		for(int i=1;i<=n;i++)
		{
			if( a[i]<=x )	continue;
			if( i>=las && a[i]>=a[i-1] )	break;
			swap( a[i],x ); ans++;
		}
		for(int i=2;i<=n;i++)
			if( a[i]<a[i-1] )	ans = -1;
		cout << ans << endl;
	}
}

以上是关于1455 D. Sequence and Swaps(思维)的主要内容,如果未能解决你的问题,请参考以下文章

[线段树 区间取模] D. The Child and Sequence

Codeforces Round #220 (Div. 2)D. Inna and Sequence 树状数组+二分

Codeforces Round #250 (Div. 1) - D. The Child and Sequence(线段树)

CodeForces 1265 D. Beautiful Sequence

Codeforces Round #604 (Div. 2) D. Beautiful Sequence(构造)

cf 1241 D. Sequence Sorting(思维)