zoukankan      html  css  js  c++  java
  • 【Educational Codeforces Round 102 C】No More Inversions

    题目链接

    链接

    翻译

    给你一个序列 (a), 是 1,2,3...k 按顺序组成的 (n (n>=k)) 个数字, 超过 (k) 了,又从右往左取。

    然后,让你确定一个排列 (p),使得它按照 (a) 中元素作为下标顺序取,得到的序列 (b) 中逆序对的个

    数不超过原序列 (a)。并且,要求得到的序列 (b) 的字典序是最大的。

    题解

    做这题之前,先得知道这么一个结论。

    s[1],s[2],s[3]...s[p-2],s[p-1],s[p],s[p-1],s[p-2]...s[1]

    这样的长度为 (2*p) 的序列,只要它满足任意两个数字都不同,那么不论 (s) 是啥,它的逆序对的个数都为 ((p-1)^2)

    这样证:从中任取两个不相同的数字 (x)(y),设他们在这个长度为 (2*p) 的序列中的相对位置如下:

    x...y...y...x 或者是 x...y....x。其中后者对应 (y) 是元素 s[p]

    那么会发现,前者无论是 (x>y) 或者 (x<y)。对逆序对贡献都是 (2),而后者对逆序对贡献都是 (1)

    那么总的逆序对数就为 (2*frac{(p-1)*(p-2)}{2}+(p-1)) 也即 ((p-1)^2)

    怎么用这个结论呢。

    我们设 (m=n-k)

    那么,(a) 根据下标就可以分为 (1..k-m-1)(k-m..k+m) 这么两段。

    而这里的第二段显然就是我们上面提到的逆序对数固定的部分,而第一部分单独不贡献逆序对,这两段之间因为第二段的

    数字都大于第一段, 所以也不会贡献逆序对.

    那么逆序对就全都在 (k-m..k+m) 这一段出现。

    则我们新得到的长度为 (n) 的序列 (b) 也应该遵循这样的规则,即第一段不贡献逆序对 1,2,...k-m-1

    然后第二段里面的值都比第一段大,但是第二段这时可以任意了,因为根据上面的证明,第二段里面数字是什么,最后

    贡献的逆序对都是一样的。

    当然选字典序最大的了,也即选 k,k-1,...k-m。这样就组成了我们的排列 (p)

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    
    int T,n,k;
    
    int main() {
    	#ifdef LOCAL_DEFINE
    		freopen("in.txt", "r", stdin);
    	#endif // LOCAL_DEFINE
    
    	cin >> T;
    	
    	while (T--) {
    		cin >> n >> k;
    		int m = n - k;
    		for (int i = 1; i <= k - m - 1; i++) {
    			cout << i << " ";
    		}
    		for (int i = k - m,j=0; i <= k; i++,j++) {
    			cout << k - j << " ";
    		}
    		cout << endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    JOINTJs笔记-5 实现节点的自动布局
    实现蛇形节点布局
    jointjs笔记4- 设置线的label,
    vue-图片src路径不存在时,显示默认图片
    vue-codemirror-merge插件的使用
    谷歌点击下载链接,闪了一下没有下载
    几个常用的正则
    vue 组件中再套用组件的情况,子组件中获取不到数据
    element-ui 组件常见错误 confirm, 分页的切换页码改变,表格样式错位
    Vue学习之路---No.7(分享心得,欢迎批评指正)
  • 原文地址:https://www.cnblogs.com/AWCXV/p/14449192.html
Copyright © 2011-2022 走看看