zoukankan      html  css  js  c++  java
  • [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();
    }
    ``
  • 相关阅读:
    论工作动力的来源是什么?答案是来自于实现自己的梦想
    向梦想者致敬
    内置函数,递归函数,模块与包,开发目录规范
    迭代器,生成器
    闭包函数,装饰器,语法糖
    函数对象,名称空间及查找,作用域
    函数调用与参数
    字符编码
    文件处理
    python 11.5数据类型及常用方法
  • 原文地址:https://www.cnblogs.com/mollnn/p/14348284.html
Copyright © 2011-2022 走看看