agc032D Rotation Sort

agc032D Rotation Sort

  • 给你一个长度为 n n n的排列 a n a_n an,通过以下两个操作将它排序:
    • 花费 A A A a i a_i ai向后移到任意一个位置。
    • 花费 B B B a i a_i ai向前移到任意一个位置。
  • 求最小花费。
  • n ≤ 5000 , 0 ≤ A , B ≤ 1 e 9 n\le5000,0\le A,B\le1e9 n5000,0A,B1e9

Solution

  • 首先一个数只会移动一次,如果移动两次不如一次到位。
  • 我们考虑哪些位置没有移动,这些位置一定是单调上升的,那么区间内的数一定要大于 a r a_r ar或小于 a l a_l al,并且一定要往两边移动,直接 n 2 n^2 n2计算这个dp即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 5005
#define ll long long 
using namespace std;

int n,i,j,k,a[maxn],A,B,s[maxn][maxn];
ll f[maxn];

int pd(int l,int r){
	return (s[r-1][a[r]-1]-s[l][a[r]-1])-(s[r-1][a[l]]-s[l][a[l]])==0;
}

ll cnt1(int l,int r){
	return s[r-1][a[l]-1]-s[l][a[l]-1];
}
ll cnt2(int l,int r){
	if (r==n+1) return 0;
	return (s[r-1][n]-s[r-1][a[r]])-(s[l][n]-s[l][a[r]]);
}

int main(){
	freopen("ceshi.in","r",stdin);
	scanf("%d%d%d",&n,&A,&B),a[0]=0,a[n+1]=n+1;
	for(i=1;i<=n;i++) scanf("%d",&a[i]);
	for(i=1;i<=n;i++) for(j=1;j<=n;j++) s[i][j]=s[i-1][j]+(a[i]<=j);
	memset(f,127,sizeof(f)),f[0]=0;
	for(i=1;i<=n+1;i++) for(j=0;j<i;j++) 
		if (a[i]>a[j]&&pd(j,i))
			f[i]=min(f[i],f[j]+cnt1(j,i)*B+cnt2(j,i)*A);
	printf("%lld",f[n+1]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值