2020牛客暑期多校训练营(第三场(E题思维构造)

, 本来不想写的,这个题流量比较少

, , . . . . . 但是一想到自己卡了这么久,哎,还是福利一下别人吧.....

简化题意

x y 暂时只考虑两个彼此相关的索引x和y

p p y = y 由于p_{p_y}=y

p y = x , p x = y ( P y x ) 那么当p_y=x时,p_x=y(由此看出P序列本质是y和x的二元组)

a , x y 那么和a联系起来,x索引和y索引的花费就是

a b s ( a x a y ) / 2 + a b s ( a y a x ) / 2 = a b s ( a x a y ) abs(a_x-a_y)/2+abs(a_y-a_x)/2=abs(a_x-a_y)

现在问题就转化为构造两个P序列

每个P序列由若干个(x,y)的二元组构成(x和y是索引,取值为1到n)

且两个P序列的二元组不能重复,求最小花费

\color{Red}开始分析

a 1   1   3   4   5   9 对于a数组是1\ 1\ 3\ 4\ 5\ 9的时候

P ( 1 , 2 ) , ( 3 , 4 ) , ( 5 , 6 ) [ 3 ] 很显然代价最小的一个P序列是(1,2),(3,4),(5,6)[由3个索引二元组构成]

a 1 = 1 , a 2 = 1 , 1 1 = 0 由于a_1=1,a_2=1,所以二元组花费是1-1=0

, 0 + 1 + 4 = 5 同理得其他二元组花费,所以总花费是0+1+4=5

现在如何开始构造代价次小的P序列呢?毕竟二元组不能和上面重复

, 您可以想一想,发现根本不好想 哈哈

, P \color{Red}换一种思路,反正最后构造的两个P序列都由二元组构成

P : ( x , y ) , ( z , w ) , ( q , e ) 对于单个P序列来说二元组是:(x,y),(z,w),(q,e)

x , y , z , w , q , e [ 1 , 6 ] 其中x,y,z,w,q,e把[1,6]都取了一遍

a y + a w + a e a x a z a q 那么代价是a_y+a_w+a_e-a_x-a_z-a_q

a 6 ( ) , a 1 ( ) 我们发现a_6的符号一定是正的(最大),a_1的符号一定是负的(最小)

所以你看看我的这种构造法

P 1 : ( 1 , 2 ) , ( 3 , 4 ) , ( 5 , 6 ) , a 6 + a 4 + a 2 a 1 a 3 a 5 P序列1:(1,2),(3,4),(5,6),花费是a_6+a_4+a_2-a_1-a_3-a_5

P 2 : ( 1 , 6 ) , ( 2 , 3 ) , ( 4 , 5 ) , a 6 + a 5 + a 3 a 1 a 2 a 4 P序列2:(1,6),(2,3),(4,5),花费是a_6+a_5+a_3-a_1-a_2-a_4

2 a 6 2 a 1 , 花费相加得到总花费是2a_6-2a_1,达到了预期的最小花费

4 , 2 a 4 2 a 1 当序列长度为4时,同样可以构造出花费最小是2a_4-2a_1

, n a 4 6 这样,就可以把长度为n的a数组分成若干个长4和长6的子区域

(显然如果能n是4的倍数全分4肯定最优,否则加一点6的区域)

(你问我为什么不分8的区域?2个4区域不必你这个优?)

d p [ i ] = m i n ( d p [ i 4 ] + a [ i ] a [ i 3 ] , d p [ i 6 ] + a [ i ] a [ i 5 ] ) 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;
	}
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107436125