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 @   June_Failure  阅读(1)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示