Codeforces Round #756 (Div. 3) 题解

A. Make Even

题目大意:给你一个数n,现在你可以选择一个长度l,让这个数的前l位数交换。请你用最少的交换次数(可以为0),使n变成偶数。如果无法达到,输出-1。
解题思路:答案只可能是-1,0,1,2,根据偶数位所出现的位置决定。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
int work() {
    int n, m = 0, flag = 0;
    cin >> n;
    if (n % 2 == 0) return 0;
    while(n > 0) {
        m = m * 10 + n % 10;
        if (n % 10 % 2 == 0) flag = 1;
        n /= 10;
    }
    if (flag == 0) return -1;
    if (m % 2 == 0) return 1;
    return 2;
}

int main()
{
    int T;
    cin >> T;
    while(T--) {
        cout << work() << endl;
    }
    return 0;
}

B. Team Composition: Programmers and Mathematicians

题目大意:有a个计算机科学家和b个数学家,现在你需要给这些人组队。组队条件:1. 每个队伍必须有4人;2.每个队伍至少有1个数学家和1个计算机科学家。问最多能组多少个队伍。
解题思路:实在懒得去想贪心了,直接二分答案。每个队伍先安排一个数学家和一个计算机科学家,然后剩下的队员随意安排即可。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
int a, b;

bool check(int x) {
    int c = a - x, d = b - x;
    if (c >= 0 && d >= 0 && (c+d)/2 >= x) return 1;
    else return 0;
}

void work() {
    cin >> a >> b;
    int l = 0, r = (a+b)/4;
    while(l <= r) {
        int mid = (l+r) / 2;
        if (check(mid)) l = mid + 1;
        else r = mid - 1;
    }
    cout << l-1 << endl;
}

int main()
{
    int T;
    cin >> T;
    while(T--) {
        work();
    }
    return 0;
}

C. Polycarp Recovers the Permutation

题目大意:有一个1-n的排列p,现在你要构造一个新的数组a。每次你需要比较p最左边的元素和p最右边的元素。如果左边的比较小,那么将这个元素插入a的最左边;如果右边的比较小,插入a的最右边,同时p中的这个元素删除。当p还剩最后一个元素的时候,你可以选择插入a的左边或者右边。
现在给你一个最终的a,请你找出任意一种p,或者无解输出-1。
解题思路:贪心和构造法。因为是1-n的排列,所以不用担心数字会重复。最大的那个数字n一定最后出去,因此你需要判断n是否在队首或者队尾。如果n在队首的话,先输出n,再把a中下标2~n-1的数字倒过来输出即可。如果n在队尾的话,把a中下标1~n-1倒过来输出,再输出0即可。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
int n, a[2000005];
void work() {
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    if (a[1] == n) {
        cout << a[1];
        for(int j = n; j >= 2; j--) cout << ' ' << a[j];
        cout << endl;
        return ;
    }
    if (a[n] == n) {
        for(int j = n-1; j >= 1; j--) cout << a[j] << ' ';
        cout << a[n] << endl;
        return ;
    }
    cout << -1 << endl;
}

int main()
{
    int T;
    cin >> T;
    while(T--) {
        work();
    }
    return 0;
}

D. Weights Assignment For Tree Edges

题目大意:给你一棵树,你需要给树上的边确定一个权值(取值范围是\(1\)~\(10^9\)),使得最后所有结点按照深度排序时,得到一个给定的序列。如果不可行,输出-1。
解题思路:构造法,深度直接定义为0~n-1即可,然后用深搜来判断合法性,最后输出deep[i] - deep[fa[i]]即可。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
using namespace std;

int n, rt;
vector <int> y[200005];
int fa[200005], deep[200005], flag;

void dfs(int u) {
    if (!flag) return ;
    for(int i = 0; i < y[u].size(); i++) {
        int v = y[u][i];
        if (deep[v] < deep[u]) flag = 0;
        else dfs(v);
    }
}

void work() {
    int a;
    cin >> n;
    for(int i = 1; i <= n; i++) y[i].clear();
    for(int i = 1; i <= n; i++) {
        cin >> fa[i];
        if (fa[i] == i) rt = i;
        else y[fa[i]].push_back(i);
    }
    for(int i = 1; i <= n; i++) {
        cin >> a;
        deep[a] = i-1;
    }
    flag = 1;
    dfs(rt);
    if (flag == 1) {
        for(int i = 1; i <= n; i++) {
            cout << deep[i] - deep[fa[i]] << ' ';
        }
        cout << endl;
    }
    else {
        cout << -1 << endl;
    }
}

int main()
{
    int T;
    cin >> T;
    while(T--) {
        work();
    }
    return 0;
}

E1. Escape The Maze (easy version)

感谢温则葆的题解
https://www.luogu.com.cn/blog/Raintime1231/solution-cf1611e1

E2. Escape The Maze (hard version)

感谢温则葆的题解
https://www.luogu.com.cn/blog/Raintime1231/solution-cf1611e2

F. ATM and Students

感谢绍嘉的题解
https://www.luogu.com.cn/blog/101868/solution-cf1611f

G. Robot and Candies

等待郑和易的题解

<

posted @ 2021-11-28 11:12  1code  阅读(219)  评论(1)    收藏  举报