[JOISC2020]ビルの飾り付け 4 题解

考虑 \(\text{DP}\)

从第一个条件得知,第一维要记录当前处理到的数字的位置 \(i\)

从第二个条件得知,第二维要记录选取的 \(A\)\(B\) 的数量 \(j\)

从第三个条件得知,第三维要记录当前选的是 \(A\) 还是 \(B\)。可以用 \(0/1\) 表示。

所以有了 \(\text{40pts}\) 做法:

\(f_{i,j,0/1}\) 表示当前处理到第 \(i\) 位,前面选取了 \(j\)\(B\) 中的数,并且当前位置选择的是 \(A/B\) 是否可行。

考虑优化。似乎一般的优化转移都不可做,所以我们选择优化状态。

将暴力的数据输出,发现对于每个固定的 \(i\)\(0/1\),可行的 \(j\) 都是连续的。

所以我们不用记录可行性而改为记录可行的左右端点

\(f_{i,0/1}\) 表示当前处理到第 \(i\) 位,并且当前位置选择的是 \(A/B\)\(B\) 的数量的上下界。

可以使用 \(\text{pair}\) 存储。转移只要四个判断即可完成。

还原出答案只需倒着循环一遍即可。

代码:

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;++i)
#define Rep(i,a,b) for(register int i=a;i>=b;--i)
inline int read()
{
    bool f=0;int x=0;char ch;
    do{ch=getchar();f|=(ch=='-');}while(!isdigit(ch));
    do{x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}while(isdigit(ch));
    return f?-x:x;
}
inline void write(int x)
{
    if(x<0)x=-x,putchar('-');
    if(x>9)write(x/10);putchar(x%10+'0');
}
inline void writesp(int x)
{
	write(x);putchar(' ');
}
inline void writeln(int x)
{
	write(x);puts("");
}
const int maxn=1e6+5;
int a[maxn],b[maxn];
pair<int,int> f[maxn][2];

void upd(pair<int,int> &x,pair<int,int> y){
	x.first=min(x.first,y.first);
	x.second=max(x.second,y.second);
}
int main()
{
	int n=read();
	rep(i,1,n<<1)a[i]=read();
	rep(i,1,n<<1)b[i]=read();
	f[0][0]=f[0][1]=make_pair(0,0);
	rep(i,1,n<<1)
	{
		f[i][0]=f[i][1]=make_pair(INT_MAX,INT_MIN);
		if(a[i-1]<=a[i])f[i][0]=make_pair(min(f[i-1][0].first,f[i][0].first),max(f[i-1][0].second,f[i][0].second));
		if(b[i-1]<=a[i])f[i][0]=make_pair(min(f[i-1][1].first,f[i][0].first),max(f[i-1][1].second,f[i][0].second));
		if(a[i-1]<=b[i])f[i][1]=make_pair(min(f[i-1][0].first,f[i][1].first),max(f[i-1][0].second,f[i][1].second));
		if(b[i-1]<=b[i])f[i][1]=make_pair(min(f[i-1][1].first,f[i][1].first),max(f[i-1][1].second,f[i][1].second));
		++f[i][1].first;++f[i][1].second;
	}
	int qaq=114514;
	if(f[n<<1][0].first<=n&&n<=f[n<<1][0].second)
	{
		qaq=0;
	}
	if(f[n<<1][1].first<=n&&n<=f[n<<1][1].second)
	{
		qaq=1;
	}
	if(qaq==114514)
	{
		puts("-1");return 0;
	}
	stack<char> ans;
	int rest=n;
	Rep(i,n<<1,1)
	{
		ans.push(qaq?'B':'A');
		rest-=qaq;
		int cur=(qaq?b[i]:a[i]);
		if(a[i-1]<=cur&&f[i-1][0].first<=rest&&f[i-1][0].second>=rest)qaq=0;
		else qaq=1;
	}
	while(!ans.empty()){putchar(ans.top());ans.pop();}
	return 0;
}
posted @ 2020-11-01 11:55  ฅ(OωO)ฅ  阅读(88)  评论(0编辑  收藏  举报
"scale": 1 }, "display": { "position": "left", "width": 100, "height": 200, "hOffset": 70, "vOffset": 0 }, "mobile": { "show": true, "scale": 0.5 }, "react": { "opacityDefault": 0.7, "opacityOnHover": 0.2 } }); window.onload = function(){ $("#live2dcanvas").attr("style","position: fixed; opacity: 0.7; left: 70px; bottom: 0px; z-index: 1; pointer-events: none;") } -->