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\),你的任务是把这些学生划分到若干个集合当中,且每个集合至少三个学生。
  • 对于每一个集合有一个差值定义为学生的能力的最大值减去最小值。
  • 问怎样划分集合可以使得差值最小。
  • 你需要输出最小差值和答案。
  • 数据范围\(3\leq n\leq2*10^5,1\leq a_i\leq10^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;
}

原文地址:https://www.cnblogs.com/zxytxdy/p/11802486.html

时间: 2024-07-31 15:58:30

CF598: div3解题报告的相关文章

解题报告 之 POJ3057 Evacuation

解题报告 之 POJ3057 Evacuation Description Fires can be disastrous, especially when a fire breaks out in a room that is completely filled with people. Rooms usually have a couple of exits and emergency exits, but with everyone rushing out at the same time

hdu 1541 Stars 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1541 题目意思:有 N 颗星星,每颗星星都有各自的等级.给出每颗星星的坐标(x, y),它的等级由所有比它低层(或者同层)的或者在它左手边的星星数决定.计算出每个等级(0 ~ n-1)的星星各有多少颗. 我只能说,题目换了一下就不会变通了,泪~~~~ 星星的分布是不是很像树状数组呢~~~没错,就是树状数组题来滴! 按照题目输入,当前星星与后面的星星没有关系.所以只要把 x 之前的横坐标加起来就可以了

【百度之星2014~初赛(第二轮)解题报告】Chess

声明 笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站,因此,笔者添加此条声明. 郑重声明:这篇记录<[百度之星2014~初赛(第二轮)解题报告]Chess>转载自 http://tiankonguse.com/ 的这条记录:http://tiankonguse.com/record/record.php?id=667 前言 最近要毕业了,有半年没做

2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告

2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告 勘误1:第6题第4个 if最后一个条件粗心写错了,答案应为1580. 条件应为abs(a[3]-a[7])!=1,宝宝心理苦啊.!感谢zzh童鞋的提醒. 勘误2:第7题在推断连通的时候条件写错了,后两个if条件中是应该是<=12 落了一个等于号.正确答案应为116. 1.煤球数目 有一堆煤球.堆成三角棱锥形.详细: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形). -. 假设一共

[noip2011]铺地毯(carpet)解题报告

最近在写noip2011的题,备战noip,先给自己加个油! 下面是noip2011的试题和自己的解题报告,希望对大家有帮助,题目1如下 1.铺地毯(carpet.cpp/c/pas) [问题描述]为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有n 张地毯,编号从1 到n.现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上.地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的

ACdream 1203 - KIDx&#39;s Triangle(解题报告)

KIDx's Triangle Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statistic Next Problem Problem Description One day, KIDx solved a math problem for middle students in seconds! And than he created this problem. N

解题报告 之 CodeForces 91B Queue

解题报告 之 CodeForces 91B Queue Description There are n walruses standing in a queue in an airport. They are numbered starting from the queue's tail: the 1-st walrus stands at the end of the queue and the n-th walrus stands at the beginning of the queue.

解题报告 之 POJ1226 Substrings

解题报告 之 POJ1226 Substrings Description You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings. Input The first li

解题报告 之 UVA563 Crimewave

解题报告 之 UVA563 Crimewave Description Nieuw Knollendam is a very modern town. This becomes clear already when looking at the layout of its map, which is just a rectangular grid of streets and avenues. Being an important trade centre, Nieuw Knollendam a