「JOISC 2020 Day1」建筑装饰 4

「JOISC 2020 Day1」建筑装饰 4

传送门

Loj

题解

考虑设\(f_{i,j,k}\)表示到了第\(i\)个位置,用了\(j\)A,\(k\)B的可行性,打表发现对于\((i,j)\)\(k\)是连续的,所以考虑记录:

\(l_{i,j}\)表示前\(i\)个位置用了\(j\)A最少用多少个B,\(r_{i,j}\)同理.

最后输出方案的时候一步一步的倒推即可.

代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define REP(a,b,c) for(int a=b;a<=c;a++)
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
typedef pair<int,int> pii;
#define mp make_pair
inline int gi()
{
	int f=1,sum=0;char ch=getchar();
	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return f*sum;
}
const int N=1000010,Inf=1e9+10;
int a[N],b[N],f[N][2],g[N][2],n;
void dfs(int id,int ex,int c)
{
	if(!id)return;
	if(f[id-1][0]<=ex&&g[id-1][0]>=ex&&a[id-1]<=(c?b[id]:a[id]))
		dfs(id-1,ex,0);
	else dfs(id-1,ex-1,1);
	putchar(c+'A');
}
int main()
{
	n=gi();
	for(int i=1;i<=n<<1;i++)a[i]=gi();
	for(int i=1;i<=n<<1;i++)b[i]=gi();
	f[1][0]=g[1][0]=0;
	f[1][1]=g[1][1]=1;
	for(int i=2;i<=n<<1;i++)
	{
		f[i][0]=f[i][1]=Inf;
		g[i][0]=g[i][1]=-Inf;
		if(a[i]>=a[i-1])
		{
			f[i][0]=min(f[i][0],f[i-1][0]);
			g[i][0]=max(g[i][0],g[i-1][0]);
		}
		if(a[i]>=b[i-1])
		{
			f[i][0]=min(f[i][0],f[i-1][1]);
			g[i][0]=max(g[i][0],g[i-1][1]);
		}
		if(b[i]>=a[i-1])
		{
			f[i][1]=min(f[i][1],f[i-1][0]+1);
			g[i][1]=max(g[i][1],g[i-1][0]+1);
		}
		if(b[i]>=b[i-1])
		{
			f[i][1]=min(f[i][1],f[i-1][1]+1);
			g[i][1]=max(g[i][1],g[i-1][1]+1);
		}
	}
	if(!((f[n<<1][0]<=n&&g[n<<1][0]>=n)||(f[n<<1][1]<=n&&g[n<<1][1]>=n)))puts("-1");
	else
	{
		if(f[n<<1][0]<=n&&g[n<<1][0]>=n)dfs(n<<1,n,0);
		else dfs(n<<1,n-1,1);
	}
	puts("");
	return 0;
}
posted @ 2020-05-09 10:59  fexuile  阅读(157)  评论(0编辑  收藏  举报