luogu p1338 末日的传说
原题链接:https://www.luogu.org/problem/show?pid=1338
这个题真是神奇,一开始写了一个n*n的式子来算,发现数据范围比我想的大的时候,果断选择O(n)算法。反正这种题跟log是没啥关系的吧。。。
然后考虑逆序对的个数,我们知道,逆序对的个数,在最大情况下,是n*(n-1)/2。
所以枚举1—n,计算当前未确定区间小数放到了后面能产生的最多逆序对是多少,如果能超过m,就把这个数扔到当前未确定区间的第一个。
如果不能,说明这个数太小了,需要放在后面增减逆序对个数,把它扔到未确定区间的最后一个。
同时,因为把一个小数放到了后面,接下来未确定区间中不管有多少逆序对,其中的每一个数,都会与这个数产生一对逆序对,所以我们需要减小m,减小的长度就是区间长度。
还有一点值得说的是,虽然50000*50000/2在int范围之内,但是计算的时候中间结果可能会溢出,所以要用long long。
#include<cstdio> long long n,m,a[50005]; int main() { scanf("%lld %lld",&n,&m); long long l=1,r=n; for(int i=1;i<=n;i++) { long long t=(n-i)*(n-i-1)/2; if(t>=m) a[l++]=i; else a[r--]=i,m-=(r-l+1); } for(int i=1;i<=n;i++) printf("%lld ",a[i]); return 0; }