选择交换.

给出长为 n 的序列 a,你可以对序列 a 进行以下操作:
选择 l,r (1 ≤ l,r ≤ n) ,交换 a[l],a[r].

请求出在任意多次操作后,序列 a 能否满足 a[1]+a[n] = a[2]+a[n-1] = a[3]+a[n-2] = ……a[n/2]+a[n+1-(n/2)].
可以证明如果有解,操作次数不大于 n.

输入
第一行包含一个整数 T (1 ≤ T ≤ 1e4),表示测试用例的组数。
每组测试用例的第一行包含一个整数 n (1 ≤ n ≤ 2e5),表示序列 a 的长度。
每组测试用例的第二行包含 n 个整数 a1,a2……,an (1 ≤ ai ≤ 1e9)。
对于所有测试用例,保证 n 的总和不超过 2e5.

输出
对于每组测试用例,如果无解,输出 "NO"。如果有解,第一行输出 "YES",第二行输出一个整数 
m (0≤m≤n),之后 m 行每行输出两个整数 l,r。

Input
2
3
1 2 2
5
3 5 1 4 7

Output
NO
YES
2
3 4
2 5

说明:对于第二组测试用例,交换后的序列为 3 7 4 1 5。

#include 
using namespace std;
#define int long long
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef pair PII;
const double PI=acos(-1.0);
const int N=2e6+10;
int n;
struct node
{
    int x,id;
}a[N];
bool cmp(node a,node b)
{
    return a.x ans;
void solve()
{
    cin>>n;
    for (int i=1;i<=n;i++) 
    {
        cin>>a[i].x;
        a[i].id=i;
    }
    sort (a+1,a+n+1,cmp);
    int l=1,r=n;
    int sum=a[l].x+a[r].x;
    bool flag=1;
    while (l<=r)                 //暴力判断
    {
        if (a[l].x+a[r].x!=sum)
        {
            flag=0;
            break;
        }
        l++,r--;
    }
    if (!flag) cout<<"NO\n";
    else 
    {
        ans.clear();
        for (int i=1;i<=n;i++)
        {
            now[i]=i;          //记录每个数现在在哪个位置
            w[i]=i;            //记录当前下标序列
        }
        for (int i=1;i<=n;i++)
        {
            int to=now[a[i].id];
            if (to!=i)
            {
                ans.push_back({i,to});
                swap(w[i],w[to]);
                now[w[i]]=i;
                now[w[to]]=to;
            }
        }
        cout<<"YES\n";
        cout<>t;
    while (t--) solve();
    return 0;
}

你可能感兴趣的:(算法,数据结构)