Codeforces Round #787 (Div. 3)ABCD

记录一下,感觉写的最好的一次了,前四个思路都很流畅。不过不太会写DFS,D调了很久很久很久 ..,E没什么思路。之后看看题解再做一做。(菜,三月份才开始做,刚到绿名。。
image

A. Food for Animals

签到题

#include <iostream>

using namespace std;

void solve()
{
    int a, b, c, x, y;
    cin >> a >> b >> c >> x >> y;
    if(max(x - a, 0) + max(y - b, 0) <= c)  puts("YES");
    else    puts("NO");
    return;
}

int main()
{
    int t = 1;
    cin >> t;
    while(t --)
    {
        solve();
    }
    return 0;
}

B. Make It Increasing

题意:对任意一个数都能操作任意次数除2,问最少操作多少次,使数组严格递增
思路:可以从倒数第二个开始往前看,若a[i] >= a[i + 1]就一直除2,直到小于为止;如果发现a[i + 1]已经是0了,说明当前这个数已经无法再变小了,就输出-1。

#include <iostream>

using namespace std;

const int N = 33;
int a[N];

void solve()
{
    int n;
    cin >> n;
    for(int i = 0; i < n; i ++ )
        cin >> a[i];
    int ans = 0;
    bool flag = true;
    for(int i = n - 2; i >= 0; i --)
    {
        if(a[i + 1] == 0)
        {
            flag = false;
            break;
        }
        while(a[i] >= a[i + 1])
        {
            a[i] /= 2;
            ans ++;
        }
    }
    if(flag)    printf("%d\n", ans);
    else    puts("-1");
    return;
}

int main()
{
    int t = 1;
    cin >> t;
    while(t --)
    {
        solve();
    }
    return 0;
}

C. Detective Task

题意:有n个人进来看画,其中有个人会偷走画,在调查时,每个人会回答0(没看到画)、1(看到了画)、?(忘记了),除了小偷之外,说的都是真话,问:有多少个偷画的嫌疑人?
思路:找到一个0,下标为t0;找到第一个1,下标为t1。t0一定有嫌疑,如果t0是偷画人,之后的人都不是嫌疑人;如果t0不是偷画人,t0之前的人要被怀疑,t0之后的不用被怀疑;t1一定有嫌疑,作为最后一个看到画的人,t1之前的都不用被怀疑。因此t1到t0之间的都是嫌疑人。
t0和t1初始化为-1
还要判断特殊情况,如果字符串中没有1和0,即都是?,那么都是嫌疑人;如果有1无0,那么t1到最后都是嫌疑人;如果有0无1,那么开始到t0都是嫌疑人。

#include <iostream>

using namespace std;

void solve()
{
    string s;
    cin >> s;
    int n = s.size();
    int t1 = -1, t0 = -1;
    for(int i = 0; i < n; i ++ )
        if(s[i] == '1') t1 = i;
    for(int i = 0; i < n; i ++ )
        if(s[i] == '0')
        {
            t0 = i;
            break;
        }
    int ans = 0;
    if(t1 == -1 && t0 == -1)    ans = n;
    else if(t1 == -1 && t0 != -1)  ans = t0 + 1;
    else if(t1 != -1 && t0 == -1)   ans = n - t1;
    else if(t1 != -1 && t0 != -1)   ans = t0 - t1 + 1;
    printf("%d\n", ans);
    return;
}

int main()
{
    int t = 1;
    cin >> t;
    while(t --)
    {
        solve();
    }
    return 0;
}

D - Vertical Paths

题意:给定一棵树,求最少的路径数,从上往下能够不重复的包括所有的点
思路:根据给出的每个点的父节点,建图,从父节点到子节点连一条边。从根节点开始dfs遍历,遍历过程中记录路径数。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 200010;
int h[N], e[N], ne[N], idx;
int p[N];
bool st[N];
vector<int> path[N];

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

void dfs(int u, int father, int &cnt)
{
    for(int i = h[u]; ~i; i = ne[i])
    {
        int j = e[i];

        if(!st[u])
        { 
            path[cnt].push_back(j);
            st[u] = true;
        }
        else path[++ cnt].push_back(j);

        dfs(j, u, cnt);
    }
}

void solve()
{
    memset(st, 0, sizeof st);
    memset(h, -1, sizeof h);
    
    int n, root;
    cin >> n;
    for(int i = 1; i <= n; i ++ )   cin >> p[i];
    
    for(int i = 1; i <= n; i ++ )
        if(p[i] != i)
            add(p[i], i);
        else    root = i;
        

    int cnt = 1;
    path[cnt].push_back(root);
    dfs(root, -1, cnt);
    printf("%d\n", cnt);
    for(int i = 1; i <= cnt; i ++ )
    {
        printf("%d\n", path[i].size());
        for(auto v : path[i])
            printf("%d ", v);
        path[i].clear();
        puts("");
    }
    puts("");
    return;
}

int main()
{
    int t = 1;
    cin >> t;
    while(t --)
    {
        solve();
    }
    return 0;
}
posted @ 2022-05-06 00:54  inss!w!  阅读(123)  评论(0编辑  收藏  举报