QAQ本来不是多难的题,然鹅我折腾了半天。看到一个挺不错的想法;
我们知道,对于一个长度为n的序列而言,其最大的逆序对的个数为n*(n-1)/2,题目是要求一个逆序数为m的字典序最小的序列。那我们不妨从1开始考虑每一个数的排列,这样每次考虑的都是当前最小的数
如果把这个数放在最前面,而剩下的数的排列的逆序数仍然可以达到m的话,那么一定要把当前考虑的这个最小的数放在最前面,这一定是最优解。即(n-i)*(n-i-1)/2。如果不行的话,为了接下来要解决的逆序数最小,应该把当前数放在最后,这样m减少的才能最多。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,m;
int main()
{
cin>>n>>m;
int fst=1,lst=n;int a[50005];
for(int i=1;i<=n;i++){
if((long long)(n-i)*(n-i-1)/2>=m)//要用longlong,否则大的数有机会直接爆int
a[fst++]=i;
else a[lst--]=i,m-=(lst-fst+1);
}
for(int i=1;i<n;i++)cout<<a[i]<<' ';
cout<<a[n]<<endl;
return 0;
}