luogu P16540 [EGOI 2026] 披萨大师 / Ovenmasters / QOJ18248 Ovenmasters 题解
我们把每个桌子上的披萨的排名放到值域上考虑。当一个桌子上的披萨要走到下一个披萨时,这两个披萨之间一定不能有其他披萨出现,也就是不能越过值域上的下一个披萨,所以会发现这些披萨在值域上的大小关系是不会改变的。
最朴素的想法是每次找到最小的能够往后走的披萨行动,但这样是 \(O(nm)\) 的。我们会发现当一个披萨往后走时,能够解放出来的披萨最多只有前面一个,所以我们从小到大移动披萨再递归到前面看是否能产生新的移动,这样字典序一定是最小的。时间复杂度线性。
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int n,m,p[N];bool vis[N];
vector<int> b[N],ans;
void dfs(int x){
while(p[x]<b[x].size()-1){
if(x<=m&&b[x][p[x]+1]>b[x+1][p[x+1]])break;
ans.push_back(b[x][++p[x]]);
if(x>1)dfs(x-1);
}
}
int main(){
// freopen("oven.in","r",stdin);
// freopen("oven.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
int l;cin>>l;
for(int j=1;j<=l;j++){
int x;cin>>x;
b[i].push_back(x);
vis[x]=1;
if(j>=2&&b[i][j-1]<b[i][j-2]){
cout<<"NO\n";
return 0;
}
}
}
for(int i=1;i<=m;i++)ans.push_back(b[i][0]);
b[m+1].push_back(-1);
for(int i=0;i<n;i++)
if(!vis[i])
b[m+1].push_back(i);
sort(b+1,b+m+2,[&](vector<int> x,vector<int> y){return x[0]<y[0];});
for(int i=1;i<=m+1;i++)dfs(i);
for(int i=1;i<=m+1;i++)
if(p[i]<b[i].size()-1){
cout<<"NO\n";
return 0;
}
cout<<"YES\n";
for(int i:ans)cout<<i<<" ";
return 0;
}

浙公网安备 33010602011771号