1. 程式人生 > 其它 >【解題報告】洛谷P6852 Mex

【解題報告】洛谷P6852 Mex

【解題報告】洛谷P6852 Mex

題目連結

https://www.luogu.com.cn/problem/P6852

思路

要求構造一個序列

我們發現,對於一個區間 \([l,r]\)\(mex\)\(val\)\([0,val-1]\) 必須都出現在這個區間中,並且 \(val\) 不能出現在這個區間中

所以我們對於某個值

  • \(val=0\)

可以變成這個 \(val\) 必須出現的 一個區間,和不能出現的很多區間

  • \(val \not =0\)

可以變成一個必須出現的區間和不能出現的區間,實際上就是把不能出現的區間並起來,剩下的就是能出現的區間了

所以我們從小到大填入一個數字 \(val\)

,每次在 \(val\) 必須出現的區間中隨便選一個點填進去

然後我們用一個集合來維護可以選擇的點,每次用二分確定還能選擇符合要求的數字,且必須在區間的左端點,然後再判斷它是不是在不能出現的區間裡面,如果不在的話,填進去,否則不填進去,然後找不在這個區間只能的能填進去的下一個位置,然後重複上述步驟即可

我們特判一下 \(0\) 的位置,然後就解決了

#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;
}
本博文為wweiyi原創,若想轉載請聯絡作者,qq:2844938982