[Codeforces Round #617 (Div. 3)] 题解 A,B,C,D,E1,E2,F

[Codeforces Round #617 (Div. 3)] 题解 A,B,C,D,E1,E2,F

1296A - Array with Odd Sum

思路:

如果一开始数组的sum和是奇数,那么直接YES,

否则:如果存在一个奇数和一个偶数,答案为YES,否则为NO

代码:

int n;
int a[maxn];

int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    int t;
    t = readint();
    while (t--)
    {
        n = readint();
        int sum = 0;
        repd(i, 1, n) {
            a[i] = readint();
            sum += a[i];
        }
        if (sum & 1)
        {
            printf("YES\n");
        } else
        {
            int isok1 = 0;
            int isok2 = 0;
            repd(i, 1, n)
            {
                if (a[i] & 1)
                {
                    isok1 = 1;
                } else
                {
                    isok2 = 1;
                }
            }
            if (isok2 == 1 & isok1 == 1)
            {
                printf("YES\n");
            } else
            {
                printf("NO\n");
            }
        }
    }

    return 0;
}

B. Food Buying

思路:

直接贪心思想模拟即可,

如果 s>9,那么花掉 \(s-s mod 10\) 的钱,还剩下 s%10+s/10 ,继续迭代。

否则 直接花掉所有钱,剩下0元,结束。

Time complexity: \(O(log_{10}(s))\)per test case.

代码:


int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    int t;
    t = readint();
    int s;
    int ans;
    while (t--)
    {
        s = readint();
        ans = 0;
        while (s)
        {
            if (s > 9)
            {
                ans += s / 10 * 10;
                s = (s % 10) + (s / 10);
            } else
            {
                ans += s;
                s = 0;
            }
        }
        printf("%d\n", ans );
    }

    return 0;
}

C. Yet Another Walking Robot

思路:

题目让删除一个长度最小的子串使机器人最后的位置不变,即如果机器人单独执行删除的子串的话,首尾位置不变。

我们设机器人的在接到第i个指令后的位置是\((xi,yi)\),用map查找下之前有没有出现过该位置。

如果有,令j = map[\((xi,yi)\)] ,那么 \([j+1,i]\) 这段子串就符合条件,维护出长度最小的符合条件的子串即可。同时用map记录(或者是更新)下位置\((xi,yi)\) -> i

map是STL中的一个容器,std::map for C++

我的代码中 map存的\((xi,yi)\) 对应的是i+1,这样在维护答案时更方便。

Time complexity: \(O(nlogn)\) per test case.

代码:

int n;
char s[maxn];
map<pii, int> m;
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    int t;
    t = readint();
    while (t--)
    {
        n = readint();
        m.clear();
        scanf("%s", s + 1);
        int x = 0;
        int y = 0;
        int len = inf;
        int l, r;
        m[mp(0, 0)] = 1;
        repd(i, 1, n)
        {
            if (s[i] == 'L')
            {
                x--;
            } else if (s[i] == 'R')
            {
                x++;
            } else if (s[i] == 'U')
            {
                y++;
            } else
            {
                y--;
            }
            if (m.count(mp(x, y)))
            {
                int j = m[mp(x, y)];
                if (i - j + 1 < len)
                {
                    len = i - j + 1;
                    l = j;
                    r = i;
                }
            }
            m[mp(x, y)] = i+1;
        }
        if (len != inf)
            printf("%d %d\n", l, r);
        else {
            printf("-1\n");
        }
    }
    return 0;
}
 

D. Fight with Monsters

思路:

很明显的,我们可以将每一个h[i]模去(a+b),得到新的h[i],如果它变成了零,让“回滚”的一个轮回。

然后对于每一个怪兽,我们需要耗费\(\lceil\frac{h_i}{a}\rceil - 1\) 次魔法。

将\(h[i] =\lceil\frac{h_i}{a}\rceil - 1\) 后,从小到大排个序后贪心取一下即可。

Time complexity: \(O(nlogn)\)

代码:

int n;
ll a, b, k;
ll h[maxn];
ll c;
std::vector<ll> v;
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    n = readint();
    a = readll(); b = readll(); k = readll();
    c = a + b;
    repd(i, 1, n)
    {
        h[i] = readll();
    }
    int ans = 0;
    repd(i, 1, n)
    {
        h[i] %= c;
        if (h[i] == 0)
            h[i] += c;
        if (h[i] <= a)
        {
            ans++;
        } else
        {
            ll t = h[i] / a;
            if (h[i] % a != 0)
            {
                t++;
            }
            v.push_back(t - 1);
        }
    }
    sort(ALL(v));
    for (auto x : v)
    {
        if (x <= k)
        {
            ans++;
            k -= x;
        }
    }
    printf("%d\n", ans );
    return 0;
}

E1. String Coloring (easy version) /1296E2 - String Coloring (hard version)

思路:

解决本问题应该清楚 狄尔沃斯定理

百科的解释为:

狄尔沃斯定理(Dilworth‘s theorem)亦称偏序集分解定理,是关于偏序集的极大极小的定理,该定理断言:对于任意有限偏序集,其最大反链中元素的数目必等于最小链划分中链的数目。此定理的对偶形式亦真,它断言:对于任意有限偏序集,其最长链中元素的数目必等于其最小反链划分中反链的数目,由偏序集P按如下方式产生的图G称为偏序集的可比图:G的节点集由P的元素组成,而e为G中的边,仅当e的两端点在P中是可比较的,有限全序集的可比图为完全图

This theorem says that the minimum number of non-decreasing sequences we need to cover the whole sequence equals the length of least decreasing subsequence.

通过分析可发现,

我们从字符串的末尾向左求最长不下降子序列,

用f[i] 代表 第i个位置在最长不下降子序列中的位置。

那么 总体就需要 $max(f[i],i\in[1,n]) $ 个颜色才能满足要求。

第i个字符就染f[i] 色即可。

E1代码:

int n;
char s[maxn];
int ans[maxn];
std::vector<char> v;
int isok = 1;
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    n = readint();
    scanf("%s", s + 1);
    ans[n] = 0;
    v.push_back(s[n]);
    for (int i = n - 1; i >= 1; --i)
    {
        int pos = lower_bound(ALL(v), s[i]) - v.begin();
        ans[i] = pos;
        if(pos==sz(v))
        {
            v.push_back(s[i]);
        }else
            v[pos] = s[i];
        if (pos > 1)
        {
            isok = 0;
        }
    }
    if (isok)
    {
        printf("YES\n");
        repd(i, 1, n)
        {
            printf("%d", ans[i]   );
        }
        printf("\n");
    } else
    {
        printf("NO\n");
    }
    return 0;
}

E2代码:

int n;
char s[maxn];
int ans[maxn];
std::vector<char> v;
int isok = 1;
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    n = readint();
    scanf("%s", s + 1);
    ans[n] = 1;
    v.push_back(s[n]);
    int ansnum = 1;
    for (int i = n - 1; i >= 1; --i)
    {
        int pos = lower_bound(ALL(v), s[i]) - v.begin();
        ans[i] = pos + 1;
        if (pos == sz(v))
        {
            v.push_back(s[i]);
        } else
            v[pos] = s[i];
        ansnum = max(ansnum, ans[i]);
    }

    printf("%d\n", ansnum);
    repd(i, 1, n)
    {
        printf("%d%c", ans[i], i == n ? '\n' : ' ' );
    }

    return 0;
}

F. Berland Beauty

思路:

首先把给定的m个限制按照降序排序,

然后降序的对于每一个限制\((ai,bi,gi)\),我们通过dfs 得出 数组\(fa[i]\) 代表 在ai到 bi 的有向路径中 到达节点i的前继节点。然后利用数组fa,更新ai到 bi 路径中边j的边值 \(f_j = max(f_j, g_i)\) ,并用bj 标记下路径中是否有边j ,满足 fj<gi 。如果没有则答案是-1,最后如果各个限制没有冲突,将那些没有更新到的边权设一个[1,1e6] 中的任意值。

代码:

int n;
int id[maxn][maxn];
int fa[maxn];
struct node
{
    int f, t, w;
    bool operator < (const node &b) const
    {
        return w > b.w;
    }
} e[maxn];
int ans[maxn];
int m;
std::vector<int> son[maxn];

void dfs(int x, int pre)
{
    for (auto y : son[x])
    {
        if (y != pre)
        {
            fa[y] = x;
            dfs(y, x);
        }
    }
}
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    n = readint();
    repd(i, 2, n)
    {
        int x, y;
        x = readint();
        y = readint();
        son[x].push_back(y);
        son[y].push_back(x);
        id[x][y] = id[y][x] = i;
    }
    m = readint();
    repd(i, 1, m)
    {
        e[i].f = readint();
        e[i].t = readint();
        e[i].w = readint();
    }
    sort(e + 1, e + 1 + m);
    int flag = 1;

    repd(i, 1, m)
    {
        dfs(e[i].f, 0);
        int now = e[i].t;
        int bj = 0;
        do
        {
            int j = id[now][fa[now]];
            if (ans[j] <= e[i].w)
            {
                bj = 1;
                ans[j] = e[i].w;
            }
            now = fa[now];
        } while (now != e[i].f);
        if (!bj)
        {
            flag = 0;
            break;
        }
    }
    if (flag)
    {
        repd(i, 2, n)
        {
            printf("%d%c", max(ans[i], 1), i == n ? '\n' : ' ');
        }
    } else
    {
        printf("-1\n");
    }
    return 0;
}
 

原文地址:https://www.cnblogs.com/qieqiemin/p/12267253.html

时间: 2024-11-07 20:28:19

[Codeforces Round #617 (Div. 3)] 题解 A,B,C,D,E1,E2,F的相关文章

Codeforces Round #617 (Div. 3) 题解

目录 Codeforces Round #617 (Div. 3) 题解 前言 A. Array with Odd Sum 题意 做法 程序 B. Food Buying 题意 做法 程序 C. Yet Another Walking Robot 题意 做法 程序 D. Fight with Monsters 题意 做法 程序 E1. String Coloring (easy version) 题意 做法 程序 E2. String Coloring (hard version) 题意 做法

Codeforces Round #617 (Div. 3) 题解 1296C 1296D 1296E 1296F

C 对每一步结束之后往map里存个位置,看停留在相同位置的最少差多少步就行了. D 由\(h\%(a+b)\leq (x+1)a\)得\(x_{min}=\lceil\frac{h\%(a+b)}{a}\rceil-1\).然后贪心即可. E1 注意到要把原字符串排序,每一对逆序对都要进行一次交换,即每一对逆序对的颜色都必须不同.因此所需的颜色数即为最长的逆序链长. 对E1,可以考虑建图,每个位置看成一个点,把每一对逆序对建边,很显然这就是判断是不是一张二分图. E2 对E2,依次考虑字母a,b

Codeforces Round #262 (Div. 2) 题解

A. Vasya and Socks time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Vasya has n pairs of socks. In the morning of each day Vasya has to put on a pair of socks before he goes to school. When

Codeforces Round #FF (Div. 2) 题解

比赛链接:http://codeforces.com/contest/447 A. DZY Loves Hash time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output DZY has a hash table with p buckets, numbered from 0 to p?-?1. He wants to insert n 

Codeforces Round #259 (Div. 2) 题解

A. Little Pony and Crystal Mine time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Twilight Sparkle once got a crystal from the Crystal Mine. A crystal of size n (n is odd; n?>?1) is an n?×?n 

Codeforces Round #177 (Div. 2) 题解

[前言]咦?现在怎么流行打CF了?于是当一帮大爷在执着的打div 1的时候,我偷偷的在刷div 2.至于怎么决定场次嘛,一般我报一个数字A,随便再拉一个人选一个数字B.然后开始做第A^B场.如果觉得机密性不高,来点取模吧.然后今天做的这场少有的AK了.(其实模拟赛只做完了4题,最后1题来不及打了) 等等,话说前面几题不用写题解了?算了,让我难得风光一下啦. [A] A. Polo the Penguin and Segments time limit per test 2 seconds mem

Codeforces Round #534 (Div. 2)题解

Codeforces Round #534 (Div. 2)题解 A. Splitting into digits 题目大意 将一个数字分成几部分,几部分求和既是原数,问如何分可以使得分出来的各个数之间的差值尽可能小 解题思路 将n分成n个1相加即可 AC代码 #include<cstring> #include<string> #include<iostream> #include<cstdio> using namespace std; int main

Codeforces Round #561 (Div. 2) 题解

Codeforces Round #561 (Div. 2) 题解 题目链接 A. Silent Classroom 水题. Code #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 105; int n; char s[N], t[N]; int main() { cin >> n; for(int i = 1; i <= n; i++) { scanf(&q

Codeforces Round #608 (Div. 2) 题解

目录 Codeforces Round #608 (Div. 2) 题解 前言 A. Suits 题意 做法 程序 B. Blocks 题意 做法 程序 C. Shawarma Tent 题意 做法 程序 D. Portals 题意 做法 程序 E. Common Number 题意 做法 程序 结束语 Codeforces Round #608 (Div. 2) 题解 前言 题目链接:仅仅只是为了方便以题目作为关键字能查找到我的题解而已(逃 Codeforces 1271A Codeforce