首页 > 其他 > 详细

【洛谷习题】末日的传说

时间:2018-10-15 22:47:21      阅读:144      评论:0      收藏:0      [点我收藏+]

题目链接:https://www.luogu.org/problemnew/show/P1338


 

不水,不水了。。。

大约一月前学了一下康托展开,初赛就考到了,看看分数,要是没学初赛就过不去了!!!

所以看到排列,我自然而然想到救过命的康托展开,但是尝试发现,是行不通的,包括next_permutation和手写一个生成排列的程序。

没办法,看题解吧,居然是O(n)的做法,本来还以为要再带上点东西的。

我们每次考虑未放过的最小的数,假如他放在从左往右第一个位置,那么剩下的最大可能产生逆序对数必须小于等于m,否则,他一定不会放在第一个位置,不管他放在哪,因他而产生的逆序对数是确定的,就是他之前空的位置。而这个数放得越靠后,剩下序列的剩下序列的逆序对数也就越少,因此其字典序也就越小,剩下的自然在最后一个位置的前面,这样最终答案的字典序也就越小,所以我们要放到最后一个位置。

技术分享图片
 1 #include <cstdio>
 2 
 3 typedef long long ll;
 4 
 5 const int maxn = 5e4 + 5;
 6 
 7 int p[maxn];
 8 
 9 int main() {
10     int n, m;
11     scanf("%d%d", &n, &m);
12     ll s = 1, t = n;
13     for (int i = 1; i <= n; ++i) {
14         if (m <= (n - i - 1LL) * (n - i) / 2) p[s++] = i;
15         else m -= t - s, p[t--] = i;
16     }
17     for (int i = 1; i <= n; ++i) printf("%d ", p[i]);
18     return 0;
19 }
AC代码

 

【洛谷习题】末日的传说

原文:https://www.cnblogs.com/Mr94Kevin/p/9795004.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!