• [CF1443E] Long Permutation


    [CF1443E] Long Permutation - 康托展开

    Description

    你需要维护一个长度为(n)的排列(P)(初态下为 1,2,3...)和(2)种操作:

    • (1 l r) 求出(sum_{i=l}^r P_i)
    • (2 x)(P)替换为(P)的下(x)个排列

    排列(P)初始为([1,2,3,cdots n])
    总共有(q)次操作

    数据范围:
    (n,qleq2 imes 10^5,xleq 10^5)

    Solution

    显然会动的只有最后的不超过 15 个数,我们用康托展开和逆康托展开暴力处理即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    int fac[20];
    
    int Cantor(vector<int> &a, int n)
    {
        int ans = 0;
        for (int i = 1; i <= n; i++)
        {
            int tmp = 0;
            for (int j = i + 1; j <= n; j++)
                if (a[j] < a[i])
                    ++tmp;
            ans += tmp * fac[n - i];
        }
        return ans;
    }
    
    vector<int> ICantor(int x, int n)
    {
        vector<int> ans(n + 2), a(n + 2), vec;
        for (int i = 1; i <= n; i++)
            vec.push_back(i);
        for (int i = 1; i <= n; i++)
        {
            a[i] = x / fac[n - i];
            x %= fac[n - i];
        }
        for (int i = 1; i <= n; i++)
        {
            ans[i] = vec[a[i]];
            vec.erase(vec.begin() + a[i]);
        }
        return ans;
    }
    
    struct Solver
    {
        int n;
        vector<int> a;
    
        Solver(int n) : n(n)
        {
            a.resize(n + 2);
            for (int i = 1; i <= n; i++)
                a[i] = i;
        }
    
        void Add(int x)
        {
            int t = Cantor(a, n);
            t += x;
            a = ICantor(t, n);
        }
    
        int Sum(int l, int r)
        {
            int ans = 0;
            for (int i = l; i <= r; i++)
                ans += a[i];
            return ans;
        }
    };
    
    signed main()
    {
        fac[0] = 1;
        for (int i = 1; i <= 16; i++)
            fac[i] = fac[i - 1] * i;
    
        int n, m;
        cin >> n >> m;
        Solver solver(min(n, 15ll));
        for (int i = 1; i <= m; i++)
        {
            int type;
            cin >> type;
            if (type == 1)
            {
                int ans = 0;
                int l, r;
                cin >> l >> r;
                if (n <= 15)
                {
                    ans = solver.Sum(l, r);
                }
                else
                {
                    int ll = n - 15 + 1, rr = n;
                    ll = max(ll, l);
                    rr = min(rr, r);
                    if (ll > rr)
                        ans = (l + r) * (r - l + 1) / 2;
                    if (ll <= rr)
                    {
                        r = min(r, n - 15);
                        if (l <= r)
                            ans = (l + r) * (r - l + 1) / 2;
                    }
                    if (ll <= rr)
                        ans += (rr - ll + 1) * (n - 15);
                    if (ll <= rr)
                        ans += solver.Sum(ll - (n - 15), rr - (n - 15));
                }
                cout << ans << endl;
            }
            else
            {
                int x;
                cin >> x;
                solver.Add(x);
            }
        }
    }
    
  • 相关阅读:
    霍夫直线检测进行复杂环境的树干提取
    matlab工具箱之人眼检测+meanshift跟踪算法--人眼跟踪
    deep learning 练习 牛顿法完成逻辑回归
    deep learning 练习 多变量线性回归
    deep learning 练习1 线性回归练习
    关于移动端键盘弹出
    关于Redux
    docker registry的CI规划
    建立自己的私有docker(ssl&login auth)
    逻辑编程
  • 原文地址:https://www.cnblogs.com/mollnn/p/14557716.html
Copyright © 2020-2023  润新知