B. Keep it Beautiful

目录

题目(中文):

个人思路:

代码:  

题目(中文):

链接:https://codeforces.com/contest/1841/problem/B

如果可以从数组的开头移除几个(可能是零)元素,并将所有这些元素以相同的顺序插入数组的后面,从而使数组以非降序的方式排序,那么数组 $[a_1, a_2, \dots, a_k]$就被称为美丽的数组。

换句话说,如果存在一个整数i\in [0,k-1],使得数组$[a_{i+1}, a_{i+2}, \dots, a_{k-1}, a_k, a_1, a_2, \dots, a_i]$以非降序排序,那么数组$[a_1, a_2, \dots, a_k]$就是美丽的。

例如

$[3, 7, 7, 9, 2, 3]$很美:我们可以去掉前面的四个元素,然后按同样的顺序插入后面的元素,这样就得到了数组 $[2, 3, 3, 7, 7, 9]$,它是按非降序排序的;
$[1, 2, 3, 4, 5]$很美:我们可以将第一个元素去掉 0 个,然后将它们插入后面,得到数组 $[1, 2, 3, 4, 5]$,它是按不降序排序的;
$[5, 2, 2, 1]$不美丽。

注意,任何由零元素或一个元素组成的数组都是美丽的。

给你一个数组 $a$,它最初是空的。你必须处理对它的$q$次查询。在$i$ 次查询中,你将得到一个整数 $x_i$,你必须执行以下操作:

- 如果你能将整数$x_i$追加到数组$a$的后,使数组$a$保持漂亮,你就必须追加它;
- 否则,什么也不用做。

每次查询后,报告是否追加了给定的整数$x_i$

输入

第一行包含一个整数$t$$1 \le t \le 10^4$)--测试用例数。

每个测试用例由两行组成。第一行包含一个整数 $q$$1 \le q \le 2 \cdot 10^5$)--查询次数。第二行包含$q$个整数$x_1, x_2, \dots, x_q$$0 \le x_i \le 10^9$)。

输入的附加限制:所有测试用例中的$q$之和不超过$2 \cdot 10^5$

输出

为每个测试用例打印一个字符串,该字符串正好由 $q$个字符组成。如果在第 $i$ 次查询时添加了整数,则字符串的第 $i$个字符应为 1;否则,应为 0。

个人思路: 

方法1:栈的思想

这里我们用第一个测试用例来将讲解:3 7 7 9 2 4 6 3 4

题目的输出的话,其实也好理解;

1:代表输入的x放进数组里面能使得数组是个好数组

0:代表输入的x放进数组里面不能能使得数组是个好数组,所以不放入数组,不需要管它了

①首先,我们判断栈(数组)是否为空,如果为空,就往数组输入第一个数,并输出1;

②其次,我们接着输入,判断现在输入的数与前面输入数(也就是q.back(),数组里面最后的一个数)的关系,如果输入的数大于等于前面输入数,则我们称之为顺序(非递减),反正则称之为逆序;

③如果为顺序,则再将该数放入数组,并输出1;

④如果为逆序的话,有两种情况;

第一种,单个数的转换过来后,能是好数组;就比如3 7 7 9 2 ,反转后就算 2 3 7 7 9,使得是个好数组;

第二种,多个数的转换过来后,能是好数组;就比如3 7 7 9 2 3,反转后就算 2 3 3 7 7 9,使得是个好数组

④第一种的顺序只可能在第二种的前面,所以这个地方要有个标记来记录一下

⑤对于第一种情况,我们可以知道只要逆序的那个数小于等于前面数组非逆序部分的第一个数,这里我们用first来记载,比如3 7 7 9 2,2要小于3 ,因此这样逆转过来就是好数组

   对于第二种情况,我们可以知道这个数不仅要小于小于等于前面数组非逆序部分的第一个数,还要大于等于第一种情况逆序的那个数字,这个地方有点抽象,用例子来看看,就比如3 7 7 9 2 33要小于等于3,且大于等于2,因此逆转过来就会是2 3 3 7 7 9,是一个好数组;

⑥对于其他情况的话,都是输出0,不需要的数

代码: 

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--) 
	{
		int n; 
		cin>>n;
		bool f=1;
		vector<int> q;
		while(n--)
		{
			int x; 
			cin>>x;
			int first;
			if(q.empty()) //放入第一个数据
			{
				q.push_back(x);
				first=x;
				cout<<1;
			}
			else if(f && x>=q.back() ) //如果没有遇到逆序,然后成非递减
			{
				q.push_back(x);
				cout<<1;
			}
			else if(x<=first && f)//发生逆序,如果当前数字小于刚开始的数字且还没操作过
			{
				q.push_back(x);
				f=0;
				cout<<1;
			}
			else if(x<=first && x>=q.back()) //有逆序,当前数字小于第一个数,且大于非递减的最后一个数字
			{
				q.push_back(x);
				f=0;
				cout<<1;
			}
			else 
				cout<<0;
		}
		cout<<endl;
	}
	return 0;
}

方法2:数组的方法

其实很前面的方法很像,原理是一样的

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
	int T;
	cin >> T;
	while (T--)
	{
		int n;
		cin >> n;
		int x = 0, f = 1;
		cin >> x;
		cout << 1;
		n --;
		int t = x;
		while (n--)
		{
			int a;
			cin >> a;
			if (x <= a && f)
			{
				cout << 1;
				x = a;
			}
			else if (x <= a && f == 0 && a <= t)
			{
				cout << 1;
				x = a;
			}
			else if (x > a && f && a <= t)
			{
				f = 0;
				cout << 1 ;
				x = a;
			}
			else 
			{
				cout << 0;
			}
			
		}
		cout << endl;
	}
}

讲解视频:  

QQ录屏20230802004551

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值