D. Lucky Permutation- 图论 -建模 -连通块

Problem - D - Codeforces

D. Lucky Permutation

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a permutation†† pp of length nn.

In one operation, you can choose two indices 1≤i<j≤n1≤i<j≤n and swap pipi with pjpj.

Find the minimum number of operations needed to have exactly one inversion‡‡ in the permutation.

†† A permutation is an array consisting of nn distinct integers from 11 to nn in arbitrary order. For example, [2,3,1,5,4][2,3,1,5,4] is a permutation, but [1,2,2][1,2,2] is not a permutation (22 appears twice in the array), and [1,3,4][1,3,4] is also not a permutation (n=3n=3 but there is 44 in the array).

‡‡ The number of inversions of a permutation pp is the number of pairs of indices (i,j)(i,j) such that 1≤i<j≤n1≤i<j≤n and pi>pjpi>pj.

Input

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

The first line of each test case contains a single integer nn (2≤n≤2⋅1052≤n≤2⋅105).

The second line of each test case contains nn integers p1,p2,…,pnp1,p2,…,pn (1≤pi≤n1≤pi≤n). It is guaranteed that pp is a permutation.

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

Output

For each test case output a single integer — the minimum number of operations needed to have exactly one inversion in the permutation. It can be proven that an answer always exists.

Example

input

Copy

 

4

2

2 1

2

1 2

4

3 4 1 2

4

2 4 3 1

output

Copy

0
1
3
1

Note

In the first test case, the permutation already satisfies the condition.

In the second test case, you can perform the operation with (i,j)=(1,2)(i,j)=(1,2), after that the permutation will be [2,1][2,1] which has exactly one inversion.

In the third test case, it is not possible to satisfy the condition with less than 33 operations. However, if we perform 33 operations with (i,j)(i,j) being (1,3)(1,3),(2,4)(2,4), and (3,4)(3,4) in that order, the final permutation will be [1,2,4,3][1,2,4,3] which has exactly one inversion.

In the fourth test case, you can perform the operation with (i,j)=(2,4)(i,j)=(2,4), after that the permutation will be [2,1,3,4][2,1,3,4] which has exactly one inversion.

---------------------------------------------------------------------------------------------------------------------------------

图论建模题目,我们把下标与ai值相连,那么在一个联通块的数字就是需要互相交换的。先不考虑使得逆序对的个数为1,考虑怎么样变成0,显然是完全归位时的情况,也就是连通块大小-1的和。

那么再考虑逆序对为1,是什么情况呢,手写几个样例会发现,是两个相邻的交换位置

1 3 2 4   ,  1 2 4 3  , 2 1 3 4其余位置不变。

那么就启示我们,我们最终归位之后,再交换一次相邻的就行了,然后我们会发现,过不了样例,原来是如果两个相邻的就在一个连通块的时候,我们是可以省去一次归位的次数的,这样就大功告成了。

# include<bits/stdc++.h>

using namespace std;
typedef long long int ll;

vector<int>v[200000+10];
int book[200000+10];
int cnt,flag;
int nowsize;
void dfs(int now)
{
    book[now]=cnt;
    nowsize++;
    if(book[now-1]==cnt||book[now+1]==cnt)
        flag=1;
    for(auto it:v[now])
    {
        if(book[it])
            continue;
        dfs(it);
    }
}
int main ()
{

    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n+1;i++)
        {
            v[i].clear();
            book[i]=0;
        }

        for(int i=1;i<=n;i++)
        {
            int x;
            cin>>x;

            v[x].push_back(i);
            v[i].push_back(x);
        }
        int ans=0;
        flag=0;
        for(int i=1;i<=n;i++)
        {
            if(book[i]==0)
            {
                cnt++;
                nowsize=0;
                dfs(i);
                ans+=(nowsize-1);

            }
        }

       // cout<<ans<< " **** "<<endl;
        if(flag)
        {
            ans--;
        }
        else
        {
            ans++;
        }

        cout<<ans<<endl;

    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qinsanma and Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值