【JOISC 2020】【UOJ501】【LOJ3271】建築裝飾(貪心)

題解:

一個顯然的思路是考慮DP f[i][0/1][j]f[i][0/1][j] 來表示長度爲 ii,以 a/ba/b 結尾,選了 jjaa 是否可行。

容易發現合法的 jj 是一個連續段,所以維護最大最小值即可。

構造的時候倒回去貪心往合法路徑走即可。


代碼:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const

namespace IO{
	inline char gc(){
		static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}template<typename T>T get_integer(){
		char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
		while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
	}inline int gi(){return get_integer<int>();}
}using namespace IO;

using std::cerr;
using std::cout;
using pii=std::pair<int,int>;
#define fi first
#define se second

template<typename T>void ckmn(T &a,cs T &b){a>b?a=b:a;}
template<typename T>void ckmx(T &a,cs T &b){a<b?a=b:a;}

cs int N=1e6+7;

int n;
int a[N],b[N];
int mn[N][2],mx[N][2];
char ans[N];

void Main(){
	n=gi();
	for(int re i=1;i<=n+n;++i)a[i]=gi();
	for(int re i=1;i<=n+n;++i)b[i]=gi();
	for(int re i=1;i<=n+n;++i){
		mn[i][0]=mn[i][1]=1e9,mx[i][0]=mx[i][1]=-1e9;
		if(a[i-1]<=a[i])
			ckmn(mn[i][0],mn[i-1][0]),ckmx(mx[i][0],mx[i-1][0]);
		if(b[i-1]<=a[i])
			ckmn(mn[i][0],mn[i-1][1]),ckmx(mx[i][0],mx[i-1][1]);
		if(a[i-1]<=b[i])
			ckmn(mn[i][1],mn[i-1][0]),ckmx(mx[i][1],mx[i-1][0]);
		if(b[i-1]<=b[i])
			ckmn(mn[i][1],mn[i-1][1]),ckmx(mx[i][1],mx[i-1][1]);
		++mn[i][0],++mx[i][0];
	}
	if(!(mn[n+n][0]<=n&&n<=mx[n+n][0])&&!(mn[n+n][1]<=n&&n<=mx[n+n][1]))
		puts("-1"),exit(0);
	bool flag=(mn[n+n][1]<=n&&n<=mx[n+n][1]);
	for(int re i=n+n,v=n;i;--i){
		ans[i]=flag?'B':'A';v-=!flag;
		int vl=flag?b[i]:a[i];
		if(a[i-1]<=vl&&mn[i-1][0]<=v&&v<=mx[i-1][0])flag=false;
		else flag=true;
	}puts(ans+1);
}

inline void file(){
#ifdef zxyoi
	freopen("building.in","r",stdin);
#endif
}signed main(){file();Main();return 0;}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章