【BOI2007】Ranklist Sorting
【BOI2007】Ranklist Sorting
Description
有一个长为的排列
每次可以选两个位置,然后将放到的位置上,代价为
求将排列变为降序的最小代价(原题要求构造方案)
Input
第一行一个数
然后读入排列
Output
一行一个数表示答案
Sample Input
4
2 3 1 4
Sample Output
8
Data Constraint
Solution
OI倒退十年是吧
首先为了方便理解,可以把降序看成升序
每个数分为两种:动与不动
显然动点只会移动一次
然后可以通过调整证明:动点从大到小/从小到大移到对应位置一定不会更劣
考虑
设表示从大到小填到,要放在原序列的位置上
此时已经按升序排好,的相对顺序与原序列相同
那么对于每个数,我们可以计算出其当前位置,记为
当动时,一定要放在的前面,即
当不动时,这一步决策会对后面的贡献值造成影响,但是我们可以将其提前计算
具体来说,设表示在原序列中的位置
对于枚举的,,一定会跨过,此时这些数全部出现
对其造成的影响就是
于是有
Code
#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define N 2010
int f[N][N],p[N],n,pos[N],ans;
int main(){
scanf("%d",&n);
F(i,1,n)scanf("%d",&p[i]),p[i]=n-p[i]+1,pos[p[i]]=i;
p[n+1]=pos[n+1]=n+1;
memset(f,127,sizeof(f));
ans=f[0][0];
f[n+1][n+1]=0;
Fd(i,n,1){
int p1=1,p2=1;
F(j,1,i-1)p1+=pos[j]<pos[i];
F(j,1,n+1){
p2+=p[j]<i;
f[i][j]=min(f[i][j],f[i+1][j]+p1+p2);
}
int sum=0;
F(j,pos[i]+1,n+1){
f[i][pos[i]]=min(f[i][pos[i]],f[i+1][j]+sum);
sum+=max(i-p[j],0);
}
}
F(i,1,n+1)ans=min(ans,f[1][i]);
printf("%d",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通