题目链接: 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;
}
蒟蒻一只,欢迎指正