[JOISC2020]ビルの飾り付け 4 題解
阿新 • • 發佈:2020-11-01
考慮 \(\text{DP}\)。
從第一個條件得知,第一維要記錄當前處理到的數字的位置 \(i\)。
從第二個條件得知,第二維要記錄選取的 \(A\) 或 \(B\) 的數量 \(j\)。
從第三個條件得知,第三維要記錄當前選的是 \(A\) 還是 \(B\)。可以用 \(0/1\) 表示。
所以有了 \(\text{40pts}\) 做法:
令 \(f_{i,j,0/1}\) 表示當前處理到第 \(i\) 位,前面選取了 \(j\) 個 \(B\) 中的數,並且當前位置選擇的是 \(A/B\) 是否可行。
考慮優化。似乎一般的優化轉移都不可做,所以我們選擇優化狀態。
將暴力的資料輸出,發現對於每個固定的 \(i\)
所以我們不用記錄可行性而改為記錄可行的左右端點。
令 \(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; }