• CF598: div3解题报告


    CF598:div3解题报告

    A: Payment Without Change

    思路:
    • 按题意模拟即可。
    代码:
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int main()
    {
        ll T;
        cin >> T;
        while(T--)
        {
            ll a, b, n, s;
            cin >> a >> b >> n >> s;
            if(a*n + b < s) puts("NO");
            else
            {
                if(s - n*a >= 0)
                {
                    s -= n * a;
                    if(s > b) puts("NO");
                    else puts("YES");
                }
                else if(s - n*a < 0)
                {
                    s = s % n;
                    if(s > b) puts("NO");
                    else puts("YES");
                }
            }
        }
        return 0;
    }
    

    B: Minimize the Permutation

    思路:
    • 从后往前扫,遇到能往左边挪的就往左边挪。
    • 当然还有位置没有挪过,那就把没有被挪过的地方记录下来,然后再贪心把小的往左边挪。
    代码:
    #include<bits/stdc++.h>
    
    using namespace std;
    const int maxn = 100 + 10;
    int a[maxn];
    int vis[maxn];
    int n;
    int main()
    {
        int T; cin >> T;
        while(T--)
        {
            cin >> n;
            for(int i = 1; i <= n; i++)
            {
                cin >> a[i];
                vis[i] = 0;
            }
            for(int i = n - 1; i >= 1; i--)
            {
                if(a[i] > a[i+1])
                {
                    swap(a[i], a[i+1]);
                    vis[i] = 1;
                }
            }
            for(int i = 1; i <= n - 1; i++)
            {
                if(vis[i] == 0)
                {
                    if(a[i] > a[i+1])
                        swap(a[i], a[i+1]);
                }
            }
            for(int i = 1; i <= n; i++)
                printf("%d ", a[i]); puts("");
    
        }
        return 0;
    }
    

    C: Platforms Jumping

    思路:
    • 贪心。
    代码:
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e3 + 10;
    int c[maxn];
    int p[maxn];
    int a[maxn];
    int n, m, d;
    
    int main()
    {
        cin >> n >> m >> d;
        int sum = 0;
        for(int i = 1; i <= m; i++)
        {
            scanf("%d", &c[i]);
            sum += c[i];
        }
    
        int cur = 0;   //当前的位置
        int right = n + 1 - sum;
        for(int i = 1; i <= m; i++)
        {
            p[i] = right;
            right += c[i];
        }
    
        right = n + 1 - sum;
        for(int i = 1; i <= m; i++) //考虑每一块木板
        {
            if(cur + d < right)  //跳不过去
            {
                p[i] = cur + d; //尽可能的贪心把木板放远一点
                cur = cur + d + c[i] - 1;
                right += c[i];
            }
            else //能跳过去
            {
                cur = n + 1;
                break;
            }
        }
    
        //最后一步还能跳
        cur += d;
    
        if(cur <= n) puts("NO");
        else
        {
            puts("YES");
            for(int i = 1; i <= m; i++)
                for(int j = p[i]; j <= p[i]+c[i]-1; j++)
                    a[j] = i;
            for(int i = 1; i <= n; i++)
                printf("%d ", a[i]);
        }
        return 0;
    }
    

    D: Binary String Minimizing

    思路:
    • 这题和B是一道题,贪心往左挪,但是有了限制,需要多注意一下。
    • 具体看代码。
    代码:
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6 + 10;
    char s[maxn];
    ll n, T, k;
    
    int main()
    {
        cin >> T;
        while(T--)
        {
            cin >> n >> k;
            scanf("%s", s+1);
            int cnt = 1;
            for(int i = 1; i <= n; i++)
            {
                if(s[i] == '0' && k >= i - cnt)
                {
                    swap(s[i], s[cnt]);
                    k -= i - cnt;
                    cnt++;
                }
                else if(s[i] == '0' && k < i - cnt && k != 0)
                {
                    for(int j = i - k; j <= i; j++)
                        if(s[j] == '1') swap(s[j], s[i]);
                    k = 0;
                }
                if(k == 0) break;
            }
            puts(s+1);
        }
        return 0;
    }
    

    E: Yet Another Division Into Teams

    题意描述:
    • 给定(n)个学生,每个学生有一个能力值(a_i),你的任务是把这些学生划分到若干个集合当中,且每个集合至少三个学生。
    • 对于每一个集合有一个差值定义为学生的能力的最大值减去最小值。
    • 问怎样划分集合可以使得差值最小。
    • 你需要输出最小差值和答案。
    • 数据范围(3leq nleq2*10^5,1leq a_ileq10^9)
    思路:
    • 首先把学生的能力值排个序。
    • 首先我们不需要考虑容量大于(5)的集合,因为我们一定可以找到更小的拆分使得结果更小。
    • 又因为我们要求集合至少有三个学生,那么每个集合也就(3-5)个人。
    • (f(i))表示遍历到了第(i)个学生的最小答案。
    • 初态(f(0)=0,f(i)=+infty)
    • 通过上面的分析,有状态转移方程。
      • (f(i+3)=min(f(i+3),f(i)+a_{i+2}-a_i))
      • (f(i+4)=min(f(i+4),f(i)+a_{i+3}-a_i))
      • (f(i+5)=min(f(i+5),f(i)+a_{i+4}-a_i))
    • 终态为(f(n))
    代码:
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 2e5 + 10;
    const int INF = 0x3f3f3f3f;
    
    struct Node{
        int val;
        int idx;
    }a[maxn];
    
    bool cmp(Node a, Node b){
        return a.val < b.val;
    }
    
    int n, f[maxn];
    int p[maxn];
    int t[maxn];
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &a[i].val);
            a[i].idx = i;
        }
    
        sort(a, a+n, cmp);
    
        memset(f, 0x3f, sizeof f);
        f[0] = 0;
    
        for(int i = 0; i < n; i++)
        {
            for(int j = 3, delta; j <= 5 && i+j <= n; j++)
            {
                delta = a[i+j-1].val - a[i].val;
                if(f[i+j] > f[i] + delta)
                {
                    p[i+j] = i;
                    f[i+j] = f[i]+delta;
                }
            }
        }
    
        int cur = n;
        int cnt = 1;
    
        while(cur != 0)
        {
            //因为sort过所以一定是连续的
            for(int i = cur - 1; i >= p[cur]; i--)
                t[a[i].idx] = cnt;
            cnt++;
            cur = p[cur];
        }
    
        cout << f[n] << " " << cnt - 1 << endl;
        for(int i = 0; i < n; i++)
            printf("%d ", t[i]); puts("");
        return 0;
    }
    
    

    F: Equalizing Two Strings

    题意描述:
    • 给你两个字符串(s)(t)长度均为(n),且只包含小写字母。
    • 每次操作你可以选取长度为(len)的序列进行如下操作。
      • (s,t)的长度为(len)子串进行倒序操作。
    • 给你两个串问是否可以通过上述操作变成相等的串。
    思路:
    • 对于两个字符串相等的首要条件是:两个字符串中每个字符出现的次数应该相同。
    • 假定现在两个字符串中出现的每个字符次数都相同了。
    • 那么如果某个字符出现两次,那么他们也可以相等。
    • 因为假设说这个出现两次的字符出现在第一个字符串,我先进行一些操作将两个相同的挨在一起(不用考虑第二个字符串如何操作)。
    • 操作完成后,对于第二个字符串,我可以交换两项,同时交换第一个字符串的相同的那两个,那么一定会得到两个字符串相等。
    • 那当我没有相同的字母怎么办?
    • 如果两个字符串的冒泡排序排成升序的次数奇偶性相同,那么可以转换成相同的字符串,反之不行。
    • 因为每次调换你可以强制相邻的两项,每次调换都会改变次数的奇偶性。
    代码:
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 30;
    int a[maxn], b[maxn];
    int n;
    
    int calc(string s)
    {
        int cnt = 0;
        for(int i = 0; i < n-1; i++)
            for(int j = 0; j < n - i; j++)
            if(s[j] > s[j+1])
        {
            cnt++;
            swap(s[j], s[j+1]);
        }
        return cnt % 2;
    }
    
    int main()
    {
        int T;
        cin >> T;
        while(T--)
        {
            memset(a, 0, sizeof(a));
            memset(b, 0, sizeof(b));
            string s, t;
            cin >> n >> s >> t;
            for(int i = 0; i < n; i++)
            {
                a[s[i]-'a']++;
                b[t[i]-'a']++;
            }
    
            bool flag = 1;
            bool jud = 0;
            for(int i = 0; i < 26; i++)
            {
                if(a[i] != b[i]) {
                    flag = 0;
                    break;
                }
    
                if(a[i] > 1) jud = 1;
            }
    
            if(!flag) {
                puts("NO");
                continue;
            }
            if(jud) {
                puts("YES");
                continue;
            }
    
            if(calc(s) == calc(t)) puts("YES");
            else puts("NO");
        }
    
        return 0;
    }
    
  • 相关阅读:
    ARMR模型简单实践作业(3)-季节性波动与差分
    ARMR模型简单实践作业(2)log()
    mac 下 basemap 安装,以及踩的一些小坑
    安装vsftpd(一)--匿名用户作业
    移动硬盘出现参数错误,无法显示
    MapperReduce序列化作业(二)——排序
    ARMR模型简单实践作业(1)-平稳性检验
    wget简单使用(2)
    基本排序算法之堆排序
    HDFS学习之客户端I/O流操作
  • 原文地址:https://www.cnblogs.com/zxytxdy/p/11802486.html
Copyright © 2020-2023  润新知