Codeforces Round#772(Div.2) C. Differential Sorting

题目

给定一个包含 n 个元素的数组 a。

您最多可以执行以下操作 n 次:选择三个索引 x,y,z (1≤x<y<z≤n) 并将 ax 替换为 ay−az。手术后,|ax|必须小于 1018

您的目标是使结果数组不递减。如果有多个解决方案,您可以输出任何一个。如果不可能实现,您也应该报告它。

输入

每个测试包含多个测试用例。第一行将包含一个整数 t (1≤t≤10000)——测试用例的数量。然后是 t 个测试用例。

每个测试用例的第一行包含一个整数 n (3≤n≤2⋅105) — 数组 a 的大小。

每个测试用例的第二行包含 n 个整数 a1,a2,…,an (−109≤ai≤109),即 a 的元素。

保证所有测试用例的 n 之和不超过 2⋅105

输出

对于每个测试用例,如果没有解决方案,则在一行中打印 -1。否则在第一行你应该打印一个整数 m (0≤m≤n)——你执行的操作数。

那么接下来的 m 行中的第 i 行应该包含三个整数 x,y,z (1≤x<y<z≤n)——第 i 次操作的描述。

如果有多个解决方案,您可以输出任何一个。请注意,您不必最小化此任务中的操作数。

题解

首先,如果 a n − 1 > a n a_{n-1}>a_{n} an1>an,那么答案是-1,因为我们不能改变最后两个元素。
如果 a n ≥ 0 a_{n}≥0 an0,则存在一个简单的解决方案:对每个1≤i≤n-2执行操作(i,n-1,n)。
否则,当且仅当初始数组已排序时,答案才存在。
证明:
假设 a n < 0 a_{n}<0 an<0 并且我们可以在 m>0 操作之后对数组进行排序。

考虑我们执行的最后一个操作 ( x m , y m , z m ) (x_{m},y_{m},z_{m}) (xm,ym,zm)。 由于最后一次运算后所有元素都应为负数,因此 a z m < 0 a_{zm}<0 azm<0 应在最后一次运算之前成立。 但是在这之后 a x m = a y m − a z m > a y m a_{xm}=a_{ym}−a_{zm}>a_{ym} axm=aymazm>aym,所以数组最后没有排序。 通过矛盾,我们证明了只要 a n < 0 a_{n}<0 an<0,我们就不能执行任何操作

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
typedef long long ll;
int n;
int a[N],b[N];
int res[N][3];
int  solve()
{
	cin >> n;
	int ans = 0;
	for (int i = 1; i <= n; i++) { cin >> a[i]; b[i] = a[i]; }
	sort(b + 1, b + 1 + n);
	int f = 0;
	for (int i = 1; i <= n; i++)
	{
		if (a[i] != b[i])f = 1;
	}
	if (f == 0)return 0;
	if (a[n] < a[n - 1])return -1;

	if (a[n] <0)
	{
		return -1;
	}
	else if(a[n]>=0)
	{
		for (int j = 1; j <= n - 2; j++)res[++ans][0] = j, res[ans][1] = n - 1, res[ans][2] = n;
	}
	return ans;
}
int main()
{
	int t;
	cin >> t;
	while (t--)
	{  
		int ans;
		ans=solve();
		if (ans == -1)cout << ans << endl;
		else
		{
			cout << ans << endl;
			for (int i = 1; i <= ans; i++)
				cout << res[i][0] << " " << res[i][1] << " " << res[i][2] << '\n';
		}
	}
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值