其他分享
首页 > 其他分享> > 「JOISC 2020 Day1」建筑装饰 4

「JOISC 2020 Day1」建筑装饰 4

作者:互联网

题意:

\(2n\)个位置,给长度为\(2n\)的序列A,B。问每一位置在\(A\)和\(B\)中任选一个,恰好\(n\)个A和B,得到不降的序列\(C\)的方案(多种任意输出一种)。

思路:

code

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
const int inf=1e9;
int n,nn,a[N],b[N],mx[N][2],mn[N][2],Mx[N],Mn[N];
void DP() {
	for(int i=1;i<=nn;i++) {
		if(a[i-1]<=a[i]) mx[i][0]=mx[i-1][0]+1;
		if(b[i-1]<=a[i]) mx[i][0]=max(mx[i][0],mx[i-1][1]+1);
		if(a[i-1]<=b[i]) mx[i][1]=mx[i-1][0];
		if(b[i-1]<=b[i]) mx[i][1]=max(mx[i][1],mx[i-1][1]);
//		printf("i=%d :  mx[i][0]=%d mx[i][1]=%d\n",i,mx[i][0],mx[i][1]);
		Mx[i]=max(mx[i][0],mx[i][1]);
	}
	for(int i=1;i<=nn;i++) {
		mn[i][0]=mn[i][1]=inf;
		if(a[i-1]<=a[i]) mn[i][0]=mn[i-1][0]+1;
		if(b[i-1]<=a[i]) mn[i][0]=min(mn[i][0],mn[i-1][1]+1);
		if(a[i-1]<=b[i]) mn[i][1]=mn[i-1][0];
		if(b[i-1]<=b[i]) mn[i][1]=min(mn[i][1],mn[i-1][1]);
//		printf("i=%d :  mn[i][0]=%d mn[i][1]=%d\n",i,mn[i][0],mn[i][1]);
		Mn[i]=min(mn[i][0],mn[i][1]);
	}
}

char pth[N];
void solve() {
//	printf("%d %d\n",Mn[nn],Mx[nn]);
	if(Mn[nn]>n||Mx[nn]<n) {printf("-1");return;}
	
	int cnta=n,lst=inf;
	for(int i=nn;i;i--) {
		if(a[i]>lst) {pth[i-1]='B';lst=b[i];}
		else if(b[i]>lst) {pth[i-1]='A';cnta--;lst=a[i];}
		else {
//			printf("i=%d: *%d [%d,%d]\n",i,cnta,Mn[i-1],Mx[i-1]);
			if(mn[i][0]<=cnta&&cnta<=mx[i][0]) {cnta--;pth[i-1]='A';lst=a[i];}
			else {pth[i-1]='B';lst=b[i];}
		}
	}
	printf("%s",pth);
}
int main() {
//	freopen("build.in","r",stdin);
//	freopen("build.out","w",stdout);
	scanf("%d",&n);nn=n<<1;
	for(int i=1;i<=nn;i++)scanf("%d",&a[i]);
	for(int i=1;i<=nn;i++)scanf("%d",&b[i]);
	DP();
	solve();
	return 0;
}

标签:cnta,int,mn,个数,Day1,JOISC,lst,2020,Mx
来源: https://www.cnblogs.com/bestime/p/16482714.html