当前位置: 首页 > 工具软件 > Swap Detector > 使用案例 >

P7726-天体探测仪(Astral Detector)【构造】

咸昀
2023-12-01

正题

题目链接:https://www.luogu.com.cn/problem/P7726


题目大意

一个长度为 n n n的排列,给出 n n n个可重集 S i S_i Si表示所有长度为 i i i的区间的最小值构成的集合。

求构造这个排列。

1 ≤ n ≤ 800 1\leq n\leq 800 1n800


解题思路

对于一个数字,如果在 S i S_i Si中的出现次数小于 i i i时,证明包含它的区间中拥有不是它为最小值的情况。
所以每个数字我们找到出现次数小于 i i i的第一个 S i S_i Si,那么它离它左右两边比他小的数字的距离就是 i − 1 i-1 i1

然后考虑再求出另一边的距离,当某个时候 S i S_i Si中不包含数字 x x x时,那么证明 x x x距离两边的距离和小于 i i i,找到一个位置就可以算出另一边的距离。

然后直接从小到大找满足条件的位置插入即可。

时间复杂度 O ( n 2 ) O(n^2) O(n2)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
const int N=810;
int n,c[N],L[N],R[N],ans[N];
set<int> s;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int x;
		memset(c,0,sizeof(c));
		for(int j=1;j<=n-i+1;j++){
			scanf("%d",&x);
			c[x]++;
		}
		for(int j=1;j<=n;j++){
			if(!L[j]&&c[j]!=i)L[j]=i-1;
			if(!R[j]&&!c[j])R[j]=i-L[j];
		}
	}
	R[1]=n-L[1]+1;
	s.insert(0);s.insert(n+1);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(ans[j])continue;
			int l=(*s.lower_bound(j))-j;
			int r=j-*(--s.upper_bound(j));
			if(l>r)swap(l,r);
			if(l==L[i]&&r==R[i])
			{ans[j]=i;s.insert(j);break;}
		}
	}
	for(int i=1;i<=n;i++)
		printf("%d ",ans[i]);
}
 类似资料: