牛客多校第五场 Drop Voicing(非常详细的证明,小白都可以看懂)

题意
在这里插入图片描述
思路

数组位置 1 2 3 4 5 6
元素值 z - - w x y

首先给出结论:对于第i个位置,插入到任意位置所需要的次数为1
证明:
考虑第n个位置,如图所示n=6
y如何插入到w与x之间

操作1:xz–wy
操作2:z–wyx

y如何插入到-与w之间

操作1:xz–wy | wxz–y
操作2:z-ywx

以此类推,就可以让第n个位置插入到任意位置
那我们如何证明对于任意i呢?
首先通过操作1,把第1…i位置全部移动到后面,
即a[i+1], a[i+2],…a[n],a[1],…,a[i]。
这样就可以把a[i]移动到任意位置,移动完毕后,把a[i+1],a[i+2],…a[n]移动到a[1],…,a[i-1]后面。
举例:
w如何插入到x与y之间

操作2:xyz–w
操作1和2(已证):xwyz–
操作2:z–xwy

证毕。

补一发AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1100;
int n;
int p[maxn], dp[maxn];
int solve(int l, int r){
 int len = 1;
 dp[1] = p[l];
 for(int i = l + 1; i <= r; i++){
  if(dp[len] <= p[i]){
   dp[++len] = p[i];
  }
  else{
   dp[upper_bound(dp + 1, dp + len + 1, p[i]) - dp] = p[i];
  }
 }
 return len;
}
int main(){
 scanf("%d", &n);
 for(int i = 1; i <= n; i++){
  scanf("%d", &p[i]);
  p[i + n] = p[i];
 }
 int ans = 0;
 for(int i = 1; i <= n; i++){
  ans = max(ans, solve(i, i + n - 1));
 }
 printf("%d\n", n - ans);
 return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44412226/article/details/107583954