1. 程式人生 > 其它 >【CF1591】【陣列陣列】【逆序對】#759(div2)D. Yet Another Sorting Problem

【CF1591】【陣列陣列】【逆序對】#759(div2)D. Yet Another Sorting Problem

題目:Problem - D - Codeforces

題解

此題是給陣列排序的題,操作是選取任意三個數,然後交換他們,確保他們的位置會發生改變。

可以交換無限次,最終可以形成一個不下降序列就輸出“YES”,否則“NO”。

只需要注意以下兩點即可解出此題:

1.如果陣列中存在兩個相同的元素,那麼就一定滿足題意,輸出“YES”

(因為這樣就可以移動任意第三個數且保證另外兩個相同的數位置不變)

2.因為不下降序列的逆序對數量為0,且每次進行交換操作一定會改變偶數個逆序對,因此當逆序對數量為偶數時,滿足題意

方法:

我是用map容器檢驗是否有重複元素,用樹狀陣列離散化來求逆序對。

注意樹狀陣列每次要初始化,且初始化範圍為每次的n,不要全部初始化,會超時。

(map也要初始化)

程式碼

#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
const int N = 5e5 + 10;
int n;
int tree[N];
map<int, int> vis;
struct node
{
    int val, id;
} a[N];
void add(int i, int v)
{
    while (i <= n)
    {
        tree[i] += v;
        i += i & -i;
    }
}
ll getsum(int i)
{
    ll res = 0;
    while (i > 0)
    {
        res += tree[i];
        i -= i & -i;
    }
    return res;
}
bool cmp(node aa, node bb)
{
    return aa.val < bb.val;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T;
    cin >> T;
    while (T--)
    {
        vis.clear();
        cin >> n;
        int f = 0;
        for (int i = 1; i <= n; ++i)
        {
            cin >> a[i].val;
            a[i].id = i;
            if (vis[a[i].val])
                f = 1;
            vis[a[i].val] = 1;
        }
        if (f)
        {
            cout << "YES" << endl;
            continue;
        }
        sort(a + 1, a + 1 + n, cmp);
        ll ans = 0;
        for (int i = 1; i <= n; ++i)
        {
            add(a[i].id, 1);
            ans += i - 1 - getsum(a[i].id - 1);
        }
        if (ans % 2 == 0)
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
        for (int i = 1; i <= n; ++i)
        {
            tree[i] = 0;
        }
    }
    return 0;
}