zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第五场) D-Drop Voicing

    链接

    https://ac.nowcoder.com/acm/contest/5670/D

    题意

    给定1~n的排列,有两种操作

    1:将倒数第二个元素放到最前面

    2:将第一个元素放到最后

    连续第一种操作若干次称为一段

    要求将该排列变为1,2,3,...,n ,且段数尽可能少,输出这个最小值

    思路

    既然若干次操作1看作一段,那我们不妨将若干次操作1当作一种操作,即选择1~n-1的最右边若干元素,将它们放到最左边

    或等价于选择1~n-1的某一元素,将它放在最右边

    我们可以发现如果将序列放在环上操作,第二种操作就仅相当于改变数字的下标,不改变元素间的相对位置

    所以我们可以将一段操作1等价于在1~n的序列中选择任一元素,将它放在最右边

    那么若干段操作1我们就可以等价于将任一元素放在任意位置

    于是我们只需找到环上的LIS,将其他不在LIS上的元素放到他们应该在的位置上即可

    代码

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define ms(a) memset(a, 0, sizeof(a))
    #define repu(i, a, b) for (int i = a; i < b; i++)
    #define repd(i, a, b) for (int i = a; i > b; i--)
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    
    const int M = int(1e5) + 5;
    const int mod = int(1e9) + 7;
    
    int a[1005];
    int d[1005];
    int lis(int s, int t) {
        ms(d);
        repu(i, s, t + 1) {
            d[i] = 1;
            repu(j, s, i) {
                if (a[j] < a[i]) {
                    d[i] = max(d[i], d[j] + 1);
                }
            }
        }
        return d[t];
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        int n;
        cin >> n;
    
        repu(i, 0, n) { cin >> a[i]; }
        repu(i, 0, n) { a[i + n] = a[i]; }
    
        int ans = -1;
        repu(i, 0, n + n) { ans = max(ans, lis(i, i + n - 1)); }
        cout << n - ans << endl;
        return 0;
    }
    
    
  • 相关阅读:
    [对对子队]会议记录4.10(Scrum Meeting 1)
    [对对子队]团队任务拆解Alpha
    [对对子队]功能规格说明书
    [对对子队]技术规格说明书
    团队项目选择
    团队作业第四次—项目系统设计与数据库设计
    团队作业第三次—项目需求分析
    团队作业第二次——团队Github实战训练
    团队作业第一次—团队展示和项目展示
    贡献分分配规则
  • 原文地址:https://www.cnblogs.com/harutomimori/p/13381177.html
Copyright © 2011-2022 走看看