• 【codeforces 501D】Misha and Permutations Summation


    【题目链接】:http://codeforces.com/problemset/problem/501/D

    【题意】

    给你两个排列;
    求出它们的字典序num1和num2;
    然后让你求出第(num1+num2)%n!个排列是什么;
    (字典序);

    【题解】

    首先。
    求出两个排列的字典序;
    ->康拓展开搞出来;
    然后得到
    v1[1](n1)!+..+v1[i](ni)!+...+v1[n](0)!
    的形式
    这里v1[i]是i+1..n中比a[i]小的数的个数;
    同样的能够得到
    v2[1](n1)!+..+v2[i](ni)!+...+v2[n](0)!
    这里v2[i]是i+1..n中比b[i]小的数的个数;
    然后考虑把两个数加起来;
    即合并成
    (v1[1]+v2[1])(n1)!+..+(v1[i]+v2[i])(ni)!+...+(v1[n]+v2[n])(0)!
    这里合并之后(v1[i]+v2[i])的值不一定会比(n-i)小;
    这就可能让某一个v1[i]+v2[i]进到前一位去;
    比如(3+3)4!进到x*5!去;
    就会让x加1
    因为(3+3)*4!可以写成(5+1)*4!的形式;
    即5!+1*4!
    也即让5!的系数+1了;
    然后4!的系数会减去5
    一直往前进位就好;
    别忘了要%n!
    所以n!的系数可以不用管它了;
    然后就能得到(num1+num2)%n!
    这个排列的康拓展开的各个
    v值了;
    从第1位开始;
    根据v[1],可以得到比a[1]小的数有多少个;
    然后直接让他等于那个v[1]+1;
    然后考虑v[2];
    这个时候仍旧能够直接得到比a[2]小的数有多少个;
    但是不能再包括a[1]了,因为是从2+1..n这个范围里面找比a[2]小的数的个数;
    根据找到的合适的位置,确定a[2]即可
    以此类推获得a[n]
    (可以用树状数组+二分搞出来)
    掌握了康拓展开、逆康拓展开吧..
    还是很优秀的。

    【Number Of WA

    0

    【完整代码】

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ms(x,y) memset(x,y,sizeof x)
    #define Open() freopen("F:\rush.txt","r",stdin)
    #define Close() ios::sync_with_stdio(0),cin.tie(0)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    const int N = 2e5+100;
    
    int n;
    
    struct BIT
    {
        int data[N];
        int lowbit(int x){
            return (-x)&x;
        }
        int get_sum(int x){
            int sum = 0;
            while (x > 0){
                sum+=data[x];
                x-=lowbit(x);
            }
            return sum;
        }
        void add(int x,int y)
        {
            while (x<=n){
                data[x]+=y;
                x+=lowbit(x);
            }
        }
        void init()
        {
            ms(data,0);
        }
    };
    
    BIT c;
    int a[N],b[N],v[N],ans[N];
    
    void kangtuo(int *a,BIT &bit){
        bit.init();
        rep1(i,1,n){
            int s = a[i]-1-bit.get_sum(a[i]-1);
            bit.add(a[i],1);
            v[i]+=s;
        }
    }
    
    int Bsearch(int l,int r,int k)
    {
        int ans = 0;
        while (l <= r)
        {
            int mid = (l+r)>>1;
            int temp = c.get_sum(mid);
            if (mid-temp>=k){
                    ans = mid;
                    r = mid-1;
            }
            else
                l = mid+1;
        }
        return ans;
    }
    
    void nikangtuo(BIT &bit){
        bit.init();
        rep1(i,1,n){
            int s = Bsearch(1,n,v[i]+1);
            ans[i] = s;
            c.add(s,1);
        }
    }
    
    int main(){
        //Open();
        Close();//scanf,puts,printf not use
        //init??????
        cin >> n;
        rep1(i,1,n)
            cin>>a[i],a[i]++;
        rep1(i,1,n)
            cin>>b[i],b[i]++;
        kangtuo(a,c);
        kangtuo(b,c);
        rep2(i,n,1){
            int you = n-i+1;
            v[i-1]+=v[i]/you;
            v[i]%=you;
        }
        nikangtuo(c);
        rep1(i,1,n)
        {
            cout<<ans[i]-1<<(i==n?'
    ':' ');
        }
        return 0;
    }
  • 相关阅读:
    压测 swoole_websocket_server 性能
    Laravel本地环境搭建:Homestead开发环境的部署
    laravel5.5框架中视图间如何共享数据?视图间共享数据的两种方法
    laravel框架模型model的创建与使用方法
    laravel学习:主从读写分离配置的实现
    《梦断代码》阅读笔记一
    数组结对开发
    对搜狗输入法的评价
    几个一
    对于大家的评审提出改进方案
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626294.html
Copyright © 2020-2023  润新知