Live2D

CF1239E Turtle

link

Solution

首先可以看出的是,如果确定上下两排的值分别是哪些,那么一定是上面从小到大,下面从大到小。因为如果存在逆序对的话交换两者一定不会更劣。

然后假设我们已经确定了长什么样,考虑最大值如何产生,设 \(\text{ans}=(1,1)\to (2,1)\to (2,n)\) 的贡献,\(w_i=(1,i+1)-(2,i)\),那么 \((1,t)\to (2,t)\to (2,n)\) 的贡献即是:

\[\text{ans}+\sum_{i=1}^{t-1} w_i \]

因为 \((1,i)\) 是递增的,\((2,i)\) 是递减的,所以 \(w_i\) 是递增的,那么最大值要么在 \((1,1)\to (2,1)\to (2,n)\) 处产生,要么在 \((1,1)\to (1,n)\to (2,n)\) 处产生。

所以我们即是最小化:

\[(1,1)+(2,n)+\max(\sum_{i=2}^{n} (1,i),\sum_{i=2}^{n} (2,i)) \]

因为可以看出 \((1,1),(2,n)\) 一定会填两个最小值,然后要最小化后面那两个。又因为后面两个的和是一定的,所以就是要让它们尽可能接近,所以我们可以背包,然后 bitset 优化即可。

复杂度 \(\Theta(n^2\sum a/\omega)\)

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define MAXM 1300000
#define MAXN 105

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}

int n,a[MAXN],b[50005];
bitset <MAXM> f[51][26];

void dfs (int i,int j,int s){
	if (!i) return ;
	if (f[i - 1][j][s])
		return dfs (i - 1,j,s);
	if (j && s >= a[i] && f[i - 1][j - 1][s - a[i]]) b[a[i]] --,dfs (i - 1,j - 1,s - a[i]),printf (" %d",a[i]);
}

signed main(){
	read (n);int m = n << 1,mxv = 0,sum = 0;
	for (Int x = 1;x <= m;++ x) read (a[x]),sum += a[x],b[a[x]] ++,chkmax (mxv,a[x]);
	sort (a + 1,a + m + 1),f[2][0][0] = 1,sum -= a[1],sum -= a[2];
	for (Int i = 3;i <= m;++ i)
		for (Int j = 0;j <= i - 1 && j <= n;++ j){
			f[i][j] = f[i - 1][j];
			if (j) f[i][j] |= f[i - 1][j - 1] << a[i];
		}
	sum /= 2;
	for (Int i = sum;~i;-- i) if (f[m][n - 1][i]){
		printf ("%d",a[1]),dfs (m,n - 1,i),putchar ('\n'),b[a[1]] --,b[a[2]] --;
		for (Int v = mxv;~v;-- v) while (b[v] --> 0) printf ("%d ",v);
		printf ("%d\n",a[2]);
		return 0;
	}
	return 0;
}
posted @ 2022-10-18 19:30  Dark_Romance  阅读(20)  评论(0编辑  收藏  举报