Atcoder AGC012F : Prefix Median

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82767527

传送门

题解:
先把 a a 排序, b b 序列能被构造出来,则:

  1. a i b i a 2 n i a_i \le b_i \le a_{2n-i}
  2. 不存在 i , j i,j i < j , a j < a i < a j + 1 i \lt j,a_j \lt a_i \lt a_{j+1} ,或者 a j + 1 < a i < a j a_{j+1} \lt a_i \lt a_j 。这个应该很好理解,因为中位数每次最多挪动1。 我们也很好构造出 a a 来对应 b b

观察到 b b 越靠后限制越强,我们从后往前DP,维护 f i , j , k f_{i,j,k} 表示第 i i 个,可选数小等于 b i + 1 b_{i+1} 的有 j j 个,大于 b i + 1 b_{i+1} 的有 k k 个。 然后枚举下一个填什么即可。 时间复杂度 O ( n 4 ) O(n^4)

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

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=105, mod=1e9+7;
inline void add(int &x,int y) {x=(x+y>=mod) ? (x+y-mod) : (x+y);}

int n,a[N];
int f[N/2][N][N];

int main() {
	n=rd();
	for(int i=1;i<=2*n-1;i++) a[i]=rd();
	sort(a+1,a+2*n);
	
	f[n][1][0]=1;
	for(int i=n-1;i>=1;i--) {
		int al=(a[i]!=a[i+1]), ar=(a[2*n-i]!=a[2*n-i-1]);
		for(int l=0;l<=2*n-1;++l)
			for(int r=0;r+l<=2*n-1;++r) if(f[i+1][l][r]) {
				int &t=f[i+1][l][r];	
				for(int dl=1;dl<=l+al;++dl) add(f[i][l+al-dl+1][r+ar+(dl>1)],t);
				for(int dr=1;dr<=r+ar;++dr) add(f[i][l+al+1][r+ar-dr],t);
			}
	}
	
	int ans=0;
	for(int l=0;l<=2*n-1;++l)
		for(int r=0;r+l<=2*n-1;++r)
			add(ans,f[1][l][r]);
	cout<<ans<<'\n';
}

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/82767527