• [CF1333D] Challenges in school №41


    [CF1333D] Challenges in school №41 - 逆序对,冒泡排序

    Description

    给定一个含 L,R 的序列,一次操作可以将若干个相邻 R,L 对翻转,问能否通过恰好 (k) 轮操作完成整个翻转过程。

    Solution

    题目给出的交换方法很容易想到冒泡排序。

    最大答案等于逆序对数,这个可以 (O(n)) 求出,最小答案不太好求。

    每次先统计出逆序对数 x,然后暴力去做一轮冒泡,但是冒泡的次数上限是 x-k。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    int n, k;
    
    int calc_n_inv(vector<int> a)
    {
        int ans = 0;
        for (int i = 0; i < n; i++)
            for (int j = n - 1; j > 0; j--)
                if (a[j - 1] > a[j])
                    swap(a[j], a[j - 1]), ++ans, j--;
        return ans;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin >> n >> k;
        vector<int> a(n);
        string str;
        cin >> str;
        for (int i = 0; i < n; i++)
        {
            char t;
            t = str[i];
            a[i] = t == 'L' ? 0 : 1;
        }
    
        int x = calc_n_inv(a);
    
        vector<vector<int>> record;
    
        int cnt = 0;
    
        while (x && k && x > k)
        {
            ++cnt;
            if (cnt > 2 * n)
                break;
            k--;
            vector<int> cur;
            for (int i = 1; i < n && x > k; i++)
            {
                if (a[i] < a[i - 1])
                {
                    swap(a[i], a[i - 1]);
                    cur.push_back(i);
                    i++;
                    x--;
                }
            }
            if (cur.size() == 0)
            {
                cout << -1;
                return 0;
            }
            record.push_back(cur);
        }
    
        while (x && x == k)
        {
            for (int i = 1; i < n; i++)
            {
                if (a[i] < a[i - 1])
                {
                    swap(a[i], a[i - 1]);
                    record.push_back(vector<int>(1, i));
                    i++;
                    x--;
                    k--;
                }
            }
        }
    
        stringstream ss;
    
        if (k || x)
        {
            ss << -1 << endl;
        }
        else
        {
            for (const auto &vec : record)
            {
                ss << vec.size() << " ";
                for (const auto &i : vec)
                    ss << i << " ";
                ss << endl;
            }
        }
        cout << ss.str();
    }
    ``
  • 相关阅读:
    linux命令
    使用JS实现前端缓存
    git放弃本地修改 强制更新
    java list
    Jquery获取select 控件的change事件时选中的值
    如何将Js代码封装成Jquery插件
    如何获取Iframe的页面控件的值
    简单的百度地图点击获取当前地理坐标
    使用Ajax上传图片到服务器(不刷新页面)
    在微信浏览器中如何让他自动关闭当前页面回到会话框js
  • 原文地址:https://www.cnblogs.com/mollnn/p/14348284.html
Copyright © 2020-2023  润新知