CF1265B Beautiful Numbers

Beautiful Numbers

思维题吧?

题目大意:给出 11nn 的任意一个排列,对于每个 ii (1in)(1\le i\le n),是否有在这个序列里面有 11ii 的任意一个排列。

先考虑这样的做法,显然如果包含 11ii 的某一个排列的话,在原序列对应的这一段的下标显然是连续的,考虑用 setset 维护 11ii 的某一个排列的下标序列。每次插入一个数就判断他的左边和右边的位置差是不是 11 即可。时间复杂度为 O(nlogn)O(n\log n)

接下来我们考虑使用双指针,也就是用 l,rl,r 维护 11ii 的任意排列的数字中下标最大或者最小的某个数的位置。原因是构成 [1,i][1,i] 的任意排列,所以在 [l,r][l,r] 中的数必然都要是 [1,i][1,i] 的数才可以。

考虑用一个变量 sumsum 维护 [l,r][l,r] 中和 [1,i][1,i] 不同的数,分情况讨论:

  • 如果当前的数出现的位置超过了 ll 或者 rr,我们就更新 llrr,同时给 sumsum 加上跳过的位置,由于 [1,i1][1,i-1] 的位置我们在以前维护过了,所以跳过的位置必然没有 [1,i1][1,i-1] 的任何数。

  • 如果当前的位置在 [l,r][l,r] 之间,那么 sumsum 减一,原因显然,[l,r][l,r] 中多了一个出现 [1,i][1,i] 的数字。

#include<bits/stdc++.h>
using namespace std;
const int N =1e6+10;
int a[N],t[N];
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int n,l,r,lmax,rmax;
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i],t[a[i]]=i;
			if(a[i]==1)
				lmax=i,rmax=i;
		}
		int sum=0;
		cout<<1;
		for(int i=2;i<=n;i++)
		{
			if(t[i]>rmax)	sum+=(t[i]-rmax-1),rmax=t[i];
			else if(t[i]<lmax)	sum+=(lmax-t[i]-1),lmax=t[i];
			else sum--;
			if(sum==0)
				cout<<1;
			else
				cout<<0;
		}
		cout<<endl;
	}
}
posted @ 2023-02-20 13:33  June_Failure  阅读(7)  评论(0)    收藏  举报  来源