• D. Yet Another Sorting Problem


    D. Yet Another Sorting Problem

    Problem - D - Codeforces

    题意

    给你一个数组,每次你可以选择一个三元组 ( i , j , k ) (i,j,k) (i,j,k)然后将 a i , a j , a k a_i,a_j,a_k ai,aj,ak 循环移动依次,问你是否可以通过若干次操作将该数组变成非递减的。

    思路

    • 思维

    ​ 首先假设三个位置是 1 , 2 , 3 1,2,3 1,2,3,可以发现你将第一个数放到某个地方之后 后续的移动就已经固定了(因为要形成要给三元环),因此可能的结果只有 2 , 3 , 1 2,3,1 2,3,1 3 , 1 , 2 3,1,2 3,1,2两种。

    ​ 如何判断是否合法?最简单的方式就是模拟一遍,从左向右一个一个复原,但是你发现 搞成 2 , 3 , 1 2,3,1 2,3,1更优,还是 3 , 1 , 2 3,1,2 3,1,2更优是不确定的。因此再观察一下性质,发现这两种方式都只会让逆序对 + 2 / − 2 +2/-2 +2/2也就是你操作一次对总逆序对的奇偶性不产生改变,所以启迪我们直接从逆序对入手,直接判断是否可行。

    ​ 然后我们刚才的考虑情况是默认三个数均不同的,发现如果三个数里存在一样的,逆序对就可能产生奇数变化,这样的话一定有解了。

    ​ 因此特判是否有相同的,然后统计一下逆序对,判断奇偶性即可。

    Code

    #include 
    #define x first
    #define y second
    #define debug(x) cout<<#x<<":"<<x<<endl;
    using namespace std;
    typedef long double ld;
    typedef long long LL;
    typedef pair<int, int> PII;
    typedef pair<double, double> PDD;
    typedef unsigned long long ULL;
    const int N = 5e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
    const double eps = 1e-8, pi = acos(-1), inf = 1e20;
    int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
    int h[N], e[M], ne[M], w[M], idx;
    void add(int a, int b, int v = 0) {
    	e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
    }
    int n, m, k;
    int a[N];
    bool st[N];
    int tr[N];
    void add(int x) {
    	for (; x <= n; x += x & -x) tr[x] ++;
    }
    int sum(int x) {
    	int res = 0;
    	for (; x; x -= x & -x) res += tr[x];
    	return res;
    }
    int main() {
    	ios::sync_with_stdio(false), cin.tie(0);
    	int T;
    	cin >> T;
    	while (T -- ) {
    		cin >> n;
    		for (int i = 1; i <= n; i ++) st[i] = false, tr[i] = 0;
    		bool ok = false;
    		for (int i = 1; i <= n; i ++) {
    			cin >> a[i];
    			if (st[a[i]]) ok = true;
    			st[a[i]] = true;
    		}
    
    		if (ok) {
    			cout << "YES\n";
    			continue ;
    		}
    		LL s = 0;
    		for (int i = n; i; i --) {
    			s += sum(a[i]);
    			add(a[i]);
    		}
    
    		if (s & 1) cout << "NO\n";
    		else cout << "YES\n";
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
  • 相关阅读:
    【K-means聚类算法】实现鸢尾花聚类
    玻色量子签约移动云“五岳”量子云计算创新加速计划!
    Swift方法mutating关键字的本质
    双端队列(Deque)
    [操作系统笔记]连续分配管理方式
    join on后面 加条件 与 where后面加条件的区别
    ChatGPT:革命性的自然语言处理技术
    Java学习Go(入门)
    Qt中的信号和槽详解
    算法笔记(三)基础提升
  • 原文地址:https://blog.csdn.net/a12377978/article/details/127613032