codeforces 题目 Reverse Sort

目录

题目:

题目理解:

思路:

AC代码:


题目:

题目理解:

给你一串长度为 n 的只含0/1的数组

目标:找到最小的操作次数,把他转换成非递减数组(0在前,1在后)

一次操作:

1.选出一个非递增子序列(前面全是1,后面全是0)

2.将距离中心位置距离相等的两个项进行互换(若长度为奇数,则中心项不动)

要输出最小操作次数,以及每次操作的子序列的项数,以及下标位置。

思路:

双指针的想法, i 指针从左边开始,j指针从右边开始。

每当我左边遇到一个1,右边遇到一个0,就说明我需要将二者进行交换。

直到我的 i 指针和 j 指针相遇。这个时刻非常重要,只可能有一下两种情况:

①我刚找完一组(左1右0)然后 i++ 到的 j 位置。

②我有左边一个多出来的1,正在右边找0,但是 j-- 到了 i 的位置。

无论那种情况,在我交换之后,我的指针左侧都将是0,而指针右侧都将是1,i 和 j 重合的这个位置是1还是0都不影响满足题目非递减(0都在左边,1都在右边)的要求。

同时也恰恰证明了,我最多需要一次操作就能满足题目的非递减(0都在左边,1都在右边)要求。

所以我们只需要左指针找1,右指针找0,每找到一对就将他们的下标存到vector中,然后排个序输出就行了。(当然一对也不需要调换的话就直接输出0)

AC代码:

#include<bits/stdc++.h>


using namespace std;

typedef long long ll;

const int N = 1e3 + 5;

char a[N];


int main()
{
	std::ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);


	int t; cin >> t;

	while (t--)
	{
		vector<int>v;

		int cnt = 0;

		int n;
		cin >> n;

		cin >> a + 1;

		for (int i = 1, j = n; i < j; i++)
		{
			if (a[i] == '0')
				continue;

			while (i < j && a[j] == '1')
			    j--;


			if (i < j)
			{
				cnt++;
				v.push_back(i);
				v.push_back(j);
				j--;
			}

		}


		if (cnt == 0)
			cout << "0" << '\n';
		else
		{
			cout << 1 << '\n';
			sort(v.begin(), v.end());

			cout << v.size() << " ";

			for (auto& i : v)
				cout << i << " ";

			cout << '\n';

		}

	}

	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值