本来不想写的,这个题流量比较少
但是一想到自己卡了这么久,哎,还是福利一下别人吧.....
简化题意
暂时只考虑两个彼此相关的索引x和y
由于ppy=y
那么当py=x时,px=y(由此看出P序列本质是y和x的二元组)
那么和a联系起来,x索引和y索引的花费就是
abs(ax−ay)/2+abs(ay−ax)/2=abs(ax−ay)
现在问题就转化为构造两个P序列
每个P序列由若干个(x,y)的二元组构成(x和y是索引,取值为1到n)
且两个P序列的二元组不能重复,求最小花费
开始分析
对于a数组是1 1 3 4 5 9的时候
很显然代价最小的一个P序列是(1,2),(3,4),(5,6)[由3个索引二元组构成]
由于a1=1,a2=1,所以二元组花费是1−1=0
同理得其他二元组花费,所以总花费是0+1+4=5
现在如何开始构造代价次小的P序列呢?毕竟二元组不能和上面重复
您可以想一想,发现根本不好想哈哈
换一种思路,反正最后构造的两个P序列都由二元组构成
对于单个P序列来说二元组是:(x,y),(z,w),(q,e)
其中x,y,z,w,q,e把[1,6]都取了一遍
那么代价是ay+aw+ae−ax−az−aq
我们发现a6的符号一定是正的(最大),a1的符号一定是负的(最小)
所以你看看我的这种构造法
P序列1:(1,2),(3,4),(5,6),花费是a6+a4+a2−a1−a3−a5
P序列2:(1,6),(2,3),(4,5),花费是a6+a5+a3−a1−a2−a4
花费相加得到总花费是2a6−2a1,达到了预期的最小花费
当序列长度为4时,同样可以构造出花费最小是2a4−2a1
这样,就可以把长度为n的a数组分成若干个长4和长6的子区域
(显然如果能n是4的倍数全分4肯定最优,否则加一点6的区域)
(你问我为什么不分8的区域?2个4区域不必你这个优?)
dp[i]=min(dp[i−4]+a[i]−a[i−3],dp[i−6]+a[i]−a[i−5])
终于完了,好累
#include <bits/stdc++.h>
using namespace std;
const int maxn=4e5+10;
long long a[maxn],dp[maxn];
int main()
{
int t,n;
cin >> t;
while(t--)
{
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i],dp[i]=1e18;
sort(a+1,a+1+n);
dp[4]=2*a[4]-2*a[1];
for(int i=6;i<=n;i++)
dp[i]=min(dp[i-4]+2*a[i]-2*a[i-3],dp[i-6]+2*a[i]-2*a[i-5]);
cout<<dp[n]<<endl;
}
}