首先我们要考虑怎么排能使逆序对数最多:显然是下降序列时,会产生n*(n-1)/2数量的逆序对
那么我们肯定是要尽量把序列的尾端安排成下降序列,前面的尽量不动,中间可能有一段排列自适应到m的逆序对数
然后考虑把每个数加进序列,如果把这个数安排在前面,那么后面最多产生(n-1)*(n-2)/2数量的逆序对数,如果这个数量都不够满足m的话
就只能把这个数安排在后面了,我们肯定想把这个数安排在序列尾端,这样能产生最多的逆序对贡献
于是就转化成了一个子问题:n,m分别为:n-1 和 m-(a的贡献),这样递归(其实不用)处理
我™又爆longlong了
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=50009; int n,m,a[maxn],head,tail; int main(){ scanf("%d%d",&n,&m);tail=n; for(int i=1;i<=n;i++){ long long t=(long long)(n-i)*(n-i-1)/2; if(t>=m)a[++head]=i; else a[tail--]=i,m-=(tail-head); } for(int i=1;i<=n;i++)printf("%d ",a[i]); }