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;
}

 

posted @ 2017-09-19 15:24  Excim  阅读(189)  评论(0编辑  收藏  举报