lb摸鱼系列1

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/zyszlb2003/article/details/99540851

题目描述

传送门

思路

就是一道火星人的升级版。

其实核心思想就是康托,但5e5的全排列受不鸟,考虑优化康托。

其实康托个数就是排列个数,根据 n = n ( n 1 ) ( n 2 ) 1 n!=n*(n-1)*(n-2)*\cdots*1

因此第一个位置可以有n种选择,由于第一个数被选了,第二个数只有(n-1)种选择,以此类推,恰好为 n n! ,正好对应进制数,第 i i 位的进制就是 n i + 1 n-i+1

再考虑 + m +m ,其实也就是字典序 + m +m ,可以将 u n k o w n unkown 进制的最低位直接加上一个m,让后模拟加法进位即可,进制数每一个位上的数 a i + 1 a_i+1 ,也就对应着康托展开第 ( a 1 + 1 ) ( a 2 + 1 ) ( a n + 1 ) (a_1+1)*(a_2+1)*\cdots*(a_n+1)

之后数据结构乱搞。

AC code

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define gc getchar()
#define ll long long
using namespace std;
const int N=5e5+10;
template<class o>
inline void qr(o &x)
{
    x=0;char c=gc;
    while(c<'0'||c>'9')c=gc;
    while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
}
void qw(ll x)
{
    if(x/10)qw(x/10);
    putchar(x%10+48);
}
ll a[N];int c[N],n; ll m;
void add(int x){for(;x<=n;x+=x&-x)++c[x];}
int ask(int x){int ans=0;for(;x;x-=x&-x)ans+=c[x];return ans;}
struct segtree{int l,r,sum;}t[N*4];int cnt;
void build(int &x,int l,int r)
{
    x=++cnt;
    if(l==r){t[x].sum=1;return ;}
    int mid=(l+r)>>1;
    build(t[x].l,l,mid);
    build(t[x].r,mid+1,r);
    t[x].sum=t[t[x].l].sum+t[t[x].r].sum;
}
void change(int l,int r,int x,int pos)
{
    --t[x].sum;
    if(l==r)return ;
    int mid=(l+r)>>1;
    if(pos<=mid)change(l,mid,t[x].l,pos);
    else change(mid+1,r,t[x].r,pos);
}
int query(int l,int r,int x,int k)
{
    if(l==r)return l;
    int mid=(l+r)>>1;
    if(k<=t[t[x].l].sum)return query(l,mid,t[x].l,k);
    else return query(mid+1,r,t[x].r,k-t[t[x].l].sum);
}
int main()
{
    //freopen("a4.in","r",stdin);
//  freopen("a4.out","w",stdout);
    qr(n),qr(m);
    for(int i=1;i<=n;i++)qr(a[i]);
    for(int i=n,x;i>=1;i--)
    {
        x=a[i];a[i]=ask(a[i]-1);
        add(x);
    }
    a[n]+=m;
    for(int i=n;i>=2;i--)
    {
        a[i-1]+=a[i]/(n-i+1);
        a[i]%=n-i+1;
    }
    int root=0;
    build(root,1,n);
    for(int i=1;i<=n;i++)
    {
        ++a[i];
        a[i]=query(1,n,1,a[i]);
        qw(a[i]),putchar(' ');
        change(1,n,1,a[i]);
    }
    puts("");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zyszlb2003/article/details/99540851
lb
今日推荐