2020 牛客多校 第五场 D-Drop Voicing(贪心 + LIS)

题目链接: D-Drop Voicing

Description

题意:给出一个序列,求通过两种操作用最少的操作次数可以把序列有序

Inaka composes music. Today’s arrangement includes a chord of n notes that are pairwise distinct, represented by a permutation p1…pn of integers from 1 to n (inclusive) denoting the notes from the lowest to the highest.
Her friend, Miyako, sneaks in and plays a trick by altering the chord with the following two operations:

  • Drop-2: Take out the second highest note and move it to the lowest position, i.e. change the permutation to pn-1, p1, p2, …, pn-2, pn;
  • Invert: Take out the lowest note and move it to the highest position, i.e. change the permutation to p2, …, pn-1, pn, p1;
    Any number of consecutive Drop-2 operations is considered a multi-drop. Miyako would like to change the permutation to an ordered permutation, 1,2, 3, …, n in the fewest number of multi-drops possible. Please help her find the number of multi-drops needed.

Input

  • The first line contains an integer n (2 ≤ n ≤ 500) — the number of notes.
  • The second line contains n space-separated integers p_1, p_2, \dots, p1, p2, p3 … pn— the original permutation of notes.
  • The input guarantees each integer from 1 to n (inclusive) appears in the permutation exactly once.

Output

Output one integer — the number of multi-drops required to change the permutation to an ordered one.

Sample Input

6
2 4 5 1 3 6

Sample Output

2

More Info

An optimal solution with two multi-drops is:

  • Invert, 5 times, changing the permutation to 6,2,4,5,1,3;
  • Drop-2, 3 times, changing the permutation to 4,5,1,6,2,3;
  • Invert, 4 times, changing the permutation to 2,3,4,5,1,6;
  • Drop-2, 1 time, changing the permutation to 1,2,3,4,5,6.

Method

  • 显然,一轮操作可以把任意一个数有序,所以可以转换成求一个序列的最长上升序列,用序列长度减去max(LIS)即最终答案;
  • 那么问题就转换成求长度为n的序列的最长上升序列(LIS), 贪心+二分即可,时间复杂度是O(nnlogn); 他是对动态规划求法的优化,动态规划求法的时间复杂度是 O(nn2);

Code

详见注释

动态规划

#include <bits/stdc++.h>

using namespace std;
#pragma GCC optimize(2)
#define ios std::ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);
#define rtxt freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#define ll long long
const int INF = 0xcfcfcf;
const int Max = 1e4+3;
const int mod = 1e9+7;

int a[Max], n, f[Max], ans=0;

int main()
{
	ios
	
	cin >> n;
	for(int i=1; i<=n; i++)
	{
		cin >> a[i];
		a[i+n] = a[i];
	}
	for(int i=1; i<=n; i++)
	{
		for(int k=1; k<=2*n; k++)
			f[k] = 1;
		for(int j=i; j<=i+n-1; j++)
		{
			for(int k=i; k<j; k++)
			{
				if(a[k] < a[j])
				f[j] = max(f[j], f[k]+1);
			}
		}
		for(int j=i; j<=i+n-1; j++)
			ans = max(ans, f[j]);
	}
	cout << n-ans << endl;
	return 0;
}

贪心 + 二分

#include <bits/stdc++.h>

using namespace std;
#pragma GCC optimize(2)
#define ios std::ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);
#define rtxt freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#define ll long long
const int Max = 1e4+3;
const int mod = 1e9+7;

int a[Max], low[Max], n, len, ans=0;

int main()
{
	ios
	
	cin >> n;
	for(int i=1; i<=n; i++)
	{
		cin >> a[i];
		a[i+n] = a[i];
	}
	for(int i=1; i<=n; i++)
	{
		for(int k=1; k<=2*n; k++)
			low[k] = INF;
		len = 1; low[1] = a[i];
		for(int j=i+1; j<i+n; j++)
		{
			if(a[j] > low[len])
				low[++len] = a[j];
			else 
				low[lower_bound(low, low+len, a[j])-low] = a[j];
		}
		ans = max(ans, len);
	}
	cout << n-ans << endl;
	return 0;
}

蒟蒻一只,欢迎指正

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值