Codeforces 1239E. Turtle 折半


原文鏈接www.cnblogs.com/zhouzhendong/p/CF1239E.html

前言

咕了這么久之后,我的博客復活了!

題解

結論1

存在一個最優解\(A\)數組,滿足\(\forall 1\leq i <n, A_{1,i}\leq A_{1,i+1}, A_{2,i}\geq A_{2,i+1}\)

證明提示:假設 \(A_{1,i} > A_{1,j},i<j\),那么,交換這兩個值之后得到的答案嚴格不劣,另一行證法相同。

結論2

\(A\)數組滿足\(\forall 1\leq i <n, A_{1,i}\leq A_{1,i+1}, A_{2,i}\geq A_{2,i+1}\)時,從左上角走到右下角存在一種方案,使得經過的權值之和最大,並且經過整個第一行或整個第二行。

證明

定義路徑 \(i\) 表示經過 \(A_{1,i}\)\(A_{2,i}\) 的合法路徑。那么可以證明,當 \(1<i<n\) 時,路徑 \(i-1\) 和路徑 \(i+1\) 中至少存在一個不劣於路徑 \(i\)

具體地,記 \(s_i\) 表示路徑 \(i\) 的權值和,那么

\[s_{i+1} - s_i = A_{1,i+1} - A_{2,i}\\ s_{i-1}-s_i = A_{2,i-1} - A_{1,i} \]

假設 \(s_i>s_{i-1},s_i>s_{i+1}\) ,那么

\[A_{1,i+1} < A_{2,i} , A_{2,i-1}<A_{1,i} \]

又因為

\[A_{1,i}\leq A_{1,i+1}, A_{2,i}\leq A_{2,i-1} \]

所以

\[A_{1,i}\leq A_{1,i+1}<A_{2,i}\leq A_{2,i-1}<A_{1,i}\Longrightarrow A_{1,i}<A_{1,i} \]

矛盾,故 \(s_i\leq s_{i-1},s_i\leq s_{i+1}\) 二者至少有一個正確。

假設 \(s_i\leq s_{i-1}\) 成立,那么 \(A_{1,i}\leq A_{2,i-1}\) ,所以 \(A_{1,i-1}\leq A_{1,i}\leq A_{2,i-1}\leq A_{2,i-2}\),所以可以得到 \(s_{i-1}\leq s_{i-2}\),即

\[s_i\leq s_{i-1} \Rightarrow s_{i-1}\leq s_{i-2} \]

於是可得 \(s_i\leq s_1\)

\(s_i\leq s_{i+1}\) ,則同理可得 \(s_i\leq s_n\)

綜上所述,\(s_i\leq s_1,s_i\leq s_n\) 二者至少有一個正確。

所以,對於 \(1<i<n\) ,必然有 \(s_1\) 或者 \(s_n\) 不劣於 \(s_i\),所以,\(\max(s_1,s_n) = \max_{i = 1}^{n} (s_i)\)

於是結論2得證。

解決問題

我們現在要解決的問題變成:將最小值和次小值分別置於左上角和右下角,其余的數分成權值和盡量平均的兩份,也就是最小化權值和的兩部分 \(\max\)

由於輸入的 \(a\) 數組值域較小,容易想到使用背包算法解決剩余的問題,並使用 bitset 優化,但是考慮到要記錄方案,無法使用 bitset

考慮數的個數不多,我們可以采用折半的方法,每一半有 \(n-1\) 個數。對於每一半,分別暴力枚舉每一個數是否被選,把所有方案狀態壓縮之后記到二維數組中。數組的兩維分別表示選了幾個數、這些數的和。

最后,再使用雙指針掃描數組獲取最優解即可。這部分可以參照代碼理解。

代碼

#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof x)
#define For(i,a,b) for (int i=(a);i<=(b);i++)
#define Fod(i,b,a) for (int i=(b);i>=(a);i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define fi first
#define se second
#define outval(x) cerr<<#x" = "<<x<<endl
#define outtag(x) cerr<<"-----------------"#x"-----------------\n"
#define outarr(a,L,R) cerr<<#a"["<<L<<".."<<R<<"] = ";\
                    For(_x,L,R) cerr<<a[_x]<<" ";cerr<<endl;
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int,int> pii;
LL read(){
    LL x=0,f=0;
    char ch=getchar();
    while (!isdigit(ch))
        f=ch=='-',ch=getchar();
    while (isdigit(ch))
        x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?-x:x;
}
const int N=26,S=N*50000;
int n,s;
vector <int> a,b;
bitset <S> va[N],vb[N];
int sta[N][S],stb[N][S];
void SolveA(int k,int cnt,int sum,int st){
	if (k==n-1){
		if (!va[cnt][sum]){
			va[cnt][sum]=1;
			sta[cnt][sum]=st;
		}
		return;
	}
	SolveA(k+1,cnt,sum,st);
	SolveA(k+1,cnt+1,sum+a[k],st|1<<k);
}
void SolveB(int k,int cnt,int sum,int st){
	if (k==n-1){
		if (!vb[cnt][sum]){
			vb[cnt][sum]=1;
			stb[cnt][sum]=st;
		}
		return;
	}
	SolveB(k+1,cnt,sum,st);
	SolveB(k+1,cnt+1,sum+b[k],st|1<<k);
}
int ans=1e9,ansa,ansb;
int res[2][N];
void chkans(int i,int j,int ap,int bp){
	int val=max(ap+bp,s-ap-bp);
	if (val<ans){
		ans=val;
		ansa=sta[i][ap];
		ansb=stb[j][bp];
	}
}
int main(){
	n=read();
	For(i,1,n*2)
		a.pb(read());
	sort(a.begin(),a.end());
	reverse(a.begin(),a.end());
	res[0][1]=a.back(),a.pop_back();
	res[1][n]=a.back(),a.pop_back();
	s=0;
	for (auto i : a)
		s+=i;
	For(i,1,n-1)
		b.pb(a.back()),a.pop_back();
	SolveA(0,0,0,0);
	SolveB(0,0,0,0);
	For(i,0,n-1){
		int j=n-1-i;
		vector <int> bp;
		For(k,0,s)
			if (vb[j][k])
				bp.pb(k);
		For(k,0,s){
			if (!va[i][k])
				continue;
			while (bp.size()>=2&&(bp[bp.size()-2]+k)*2>=s)
				bp.pop_back();
			if (bp.size()>0)
				chkans(i,j,k,bp.back());
			if (bp.size()>=2)
				chkans(i,j,k,bp[bp.size()-2]);
		}
	}
	int t0=1,t1=0;
	For(i,0,n-2)
		if (ansa>>i&1)
			res[0][++t0]=a[i];
		else
			res[1][++t1]=a[i];
	For(i,0,n-2)
		if (ansb>>i&1)
			res[0][++t0]=b[i];
		else
			res[1][++t1]=b[i];
	sort(res[0]+2,res[0]+n+1);
	sort(res[1]+1,res[1]+n);
	reverse(res[1]+1,res[1]+n);
	For(i,0,1){
		For(j,1,n)
			printf("%d ",res[i][j]);
		puts("");
	}
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM