B. Stepan and Permutation|一行 gcd 直接秒杀,不会并查集也能做!

time limit per test

2 seconds

memory limit per test

256 megabytes

Stepan found a permutation p of length n. Of course, he decided to sort it. To make the process more interesting, he chose two positive integers x and y (x+y≤n) and defined a rule for swapping elements.

In one move, Stepan can choose two indices i and j (1≤i,j≤n) and swap the elements pi and pj if at least one of the following conditions holds:

  • |i−j|=x
  • |i−j|=y

Stepan wants to know whether it is possible to sort the permutation in ascending order using any number of such operations. Help him answer this question.

Input

The first line contains a single integer t (1≤t≤104) — the number of test cases.

The first line of each test case contains three integers n, x, and y (1≤x,y≤n≤2⋅105, x+y≤n) — the length of the array and the numbers chosen by Stepan.

The second line of each test case contains n integers pi (1≤pi≤n) — the array p; it is guaranteed that p is a permutation.

It is guaranteed that the sum of n over all test cases does not exceed 2⋅105.

Output

For each test case, output "YES" if it is possible to sort the permutation with the given x and y, and "NO" otherwise.

You may output each letter in any case (lowercase or uppercase). For example, the strings "yEs", "yes", "Yes", and "YES" will be accepted.

Example

Input

4

5 2 3

5 4 3 2 1

6 2 4

2 1 4 3 6 5

4 2 2

1 2 3 4

5 2 3

1 2 3 5 4

Output

YES

NO

YES

YES

两个位置能不能互相移动,取决于它们对 gcd(x,y) 取模是否相同。

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<map>
#define int long long
using namespace std;
struct node
{
	int val;
	int idx;
};
bool cmp(struct node a, struct node b)
{
	return a.val < b.val;
}
int gcd(int x, int y)
{
	return y == 0 ? x : gcd(y, x % y);
}
vector<int>fat;//记录每个位置属于哪一组
bool solve()
{
	int n, x, y;
	cin >> n >> x >> y;
	vector<struct node>a(n);
	for (int i = 0;i < n;i++)
	{
		cin >> a[i].val;
		a[i].idx = i;
	}
	int g = gcd(x, y);
	sort(a.begin(), a.end(), cmp);
	fat.resize(n);
	for (int i = 0;i < n;i++)
		fat[i] = i % g;
	for (int i = 0;i < n;i++)
	{
		//目标位置和原位置要在同一组才能交换
		if (fat[a[i].idx] != fat[i])
			return false;
	}
	return true;
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		if (solve())
			cout << "YES\n";
		else
			cout << "NO\n";
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值