【解題報告】洛谷P6852 Mex
阿新 • • 發佈:2021-10-13
【解題報告】洛谷P6852 Mex
題目連結
https://www.luogu.com.cn/problem/P6852
思路
要求構造一個序列
我們發現,對於一個區間 \([l,r]\) 的 \(mex\) 為 \(val\) ,\([0,val-1]\) 必須都出現在這個區間中,並且 \(val\) 不能出現在這個區間中
所以我們對於某個值
- \(val=0\)
可以變成這個 \(val\) 必須出現的 一個區間,和不能出現的很多區間
- \(val \not =0\)
可以變成一個必須出現的區間和不能出現的區間,實際上就是把不能出現的區間並起來,剩下的就是能出現的區間了
所以我們從小到大填入一個數字 \(val\)
然後我們用一個集合來維護可以選擇的點,每次用二分確定還能選擇符合要求的數字,且必須在區間的左端點,然後再判斷它是不是在不能出現的區間裡面,如果不在的話,填進去,否則不填進去,然後找不在這個區間只能的能填進去的下一個位置,然後重複上述步驟即可
我們特判一下 \(0\) 的位置,然後就解決了
本博文為wweiyi原創,若想轉載請聯絡作者,qq:2844938982#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <string> #include <set> using namespace std; const int maxn=500005; int n,m; int loc[maxn],roc[maxn]; int lb[maxn],rb[maxn]; int pre[maxn],ans[maxn]; bool flag; set <int> s; int main() { cin>>n>>m; for(int i=0;i<=n;i++) s.insert(i); for(int i=0;i<=n+1;i++) { loc[i]=0,roc[i]=n; lb[i]=n+1,rb[i]=-1; } for(int i=1;i<=m;i++) { int x,y,val; cin>>x>>y>>val; if(val) { loc[val-1]=max(loc[val-1],x); roc[val-1]=min(roc[val-1],y); lb[val]=min(lb[val],x),rb[val]=max(rb[val],y); } else { pre[x]++; pre[y+1]--; } } for(int i=n;i>=0;i--) { loc[i]=max(loc[i],loc[i+1]); roc[i]=min(roc[i],roc[i+1]); } for(int i=0;i<=n;i++) { pre[i]+=pre[i-1]; if(loc[0]<=i&&i<=roc[0]&&pre[i]==0) { ans[i]=0; s.erase(i); break; } } for(int i=1;i<=n;i++) { set <int>::iterator it=s.lower_bound(loc[i]); if(it!=s.end()&&*it<=roc[i]&&(lb[i]>*it||*it>rb[i])) { ans[*it]=i; s.erase(it); } else if(rb[i]!=-1) { it=s.lower_bound(rb[i]+1); if(it!=s.end()&&*it<=roc[i]) { ans[*it]=i; s.erase(it); } } } if(s.size()) cout<<-1<<'\n'; else { for(int i=0;i<=n;i++) cout<<ans[i]<<" "; cout<<'\n'; } return 0; }