• D. Nastya Is Buying Lunch


    https://codeforces.com/contest/1136/problem/D

    这个题目说是一个贪心,并没有看出来,然后搜了题解。

    对于题解的理解:首先就是要知道,设num[x]表示x之后的可以交换的点的数量,易得如果一个点的num==n-i-ans

    这个就说明可以向前移动一位,这个ans就是答案。

    仔细思考,感觉其实没有这么简单,有一些处理非常巧妙,比如说这个num数组,

    这个数组首先记录的是最后一个点到前面每一个点可以到达的,如果可以到达那就是1,否则就是0,

    这个进入下面一层for循环之后,就可以判断最后可不可以和前面一位进行交换,如果不可以,

    这个时候就会再次更新num,如果前面的可以和倒数第二个进行交换,就num++,这样子,

    (这个详细说明一下,这个更新就是去考虑倒数第二个和前面的连在一起的点。)

    再次判断是不是有一个num==2,如果有就可以把最后一个向前移动一位,如果没有继续往下走。

    因为这些移动是不可逆的,这个就说明你可以从n-1一直判断到1。这个需要好好思考。

    要注意这个num什么时候才会更新,这个num只有它不可以往前面移动的时候,才会去更新。

    这个很难想。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<vector>
    #define inf 0x3f3f3f3f
    #define debug(x) cout<<"-----"<<" x = "<<x<<"-----"<<endl
    using namespace std;
    typedef long long ll;
    const int  mod = 1e8;
    const int maxn = 5e5 + 10;
    vector<int>vec[maxn];
    int a[maxn], num[maxn];
    
    int main()
    {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for(int i=1;i<=m;i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            vec[v].push_back(u);
        }
        int ans = 0;
        for (int i = 0; i < vec[a[n]].size(); i++) num[vec[a[n]][i]]++;
        for(int i=n-1;i>=1;i--)
        {
            if (num[a[i]] == n - i - ans) ans++;
            else
            {
                for (int j = 0; j < vec[a[i]].size(); j++) num[vec[a[i]][j]]++;
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    一、vue常用指令
    win10安装和配置node
    win10安装和配置java8
    二、vue-cli4.5脚手架创建vue项目
    配置分布式事务实例:springcloud-Hoxton.SR1+springboot2.2.2+nacos1.3.2+seata1.2.0
    centos7安装frps_0.31.1
    centos7安装nginx1.18.0
    docker安装nexus3
    centos7防火墙的配置
    centos7使用Apache实现HTTP访问SVN资源库
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/10902571.html
Copyright © 2020-2023  润新知