zoukankan      html  css  js  c++  java
  • Codeforces Round #656 (Div. 3)

    A. Three Pairwise Maximums

    大意:

    给出三个数xyz,问能否找到3个数abc,使得(x=max(a,b), y=max(a,c) ,z=max(b,c))

    思路:

    如果任意两个数的最大值都相同,那么有解,否则无解

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    int t;
    int main() {
        cin >> t;
        while (t--) {
            int x, y, z;
            cin >> x >> y >> z;
            if (max(x, y) == max(y, z) && max(x, y) == max(x, z)) {
                cout << "YES" << endl;
                cout << min({x, y, z}) << ' ' << min({x, y, z}) << ' ' << max({x, y, z}) << endl;
            } else
                cout << "NO" << endl;
        }
        return 0;
    }
    

    B. Restore the Permutation by Merger

    大意:

    给出一个长度为2n的数组,这个数组是由2个完全相同的1到n的全排列按照原本的顺序交叉组成的,问这个1到n的全排列是什么

    思路:

    每个数第一次遇到的时候输出即可

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    int t;
    int vis[55];
    int main() {
        cin >> t;
        while (t--) {
            int n;
            cin >> n;
            memset(vis, 0, sizeof vis);
            for (int i = 0; i < 2 * n; i++) {
                int x;
                cin >> x;
                if (vis[x] == 0) {
                    vis[x] = 1;
                    cout << x << ' ';
                }
            }
            cout << endl;
        }
        return 0;
    }
    

    C. Make It Good

    大意:

    给出一个数组,问最少删除多少个前缀,可以使得剩下的数组为一个好数组

    好数组的定义是每次从数组的前面或者后面取出一个数,放到新数组里,全部取完后新数组为单调不减数组

    思路:

    好数组必然是一个先增后降的数组,所以从后往前找到这个区间即可

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    int t, a[N];
    int main() {
        cin >> t;
        while (t--) {
            int n;
            cin >> n;
            for (int i = 0; i < n; i++) {
                cin >> a[i];
            }
            int mid = 0;
            for (int i = n - 1; i >= 1; i--) {
                if (a[i] > a[i - 1]) {
                    mid = i - 1;
                    break;
                }
            }
            int res = 0;
            if (mid != 0) {
                for (int i = mid; i >= 0; i--) {
                    if (a[i] < a[i - 1]) {
                        res = i;
                        break;
                    }
                }
            }
            cout << res << endl;
        }
        return 0;
    }
    

    D. a-Good String

    大意:

    c-Good 串的定义是满足一下条件之一的串:

    如果长度为1,那么字符串等于c

    如果长度大于1,那么左半边字符串的字符都是c,右半边的字符串是(c+1)-Good串

    如果长度大于1,那么右半边字符串的字符都是c,左半边的字符串是(c+1)-Good串

    现在给出一个长度为n的串,问最少修改多少次可以使得字符串为a-Good串

    思路:

    dp,先算z-good串,再算y-good串,最后算出a-good串即可

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 2e5 + 5;
    typedef long long LL;
    int t, n, l, dp[30][N];
    string s;
    int main() {
        cin >> t;
        while (t--) {
            cin >> n;
            cin >> s;
            n = log2(n);
            l = s.size();
            // cout << n << endl;
            if (n == 0) {
                cout << (s[0] != 'a') << endl;
                continue;
            }
            for (int i = 0; i < l; i++) {
                dp[0][i] = (s[i] != ('a' + n));
            }
            for (int i = 1; i <= n; i++) {
                int len = pow(2, i - 1);
                bool left = 1;
    
                for (int j = 0; j < l; j += len) {
                    int base = 0;
                    for (int k = j; k < j + len; k++) {
                        base += (s[k] != ('a' + n - i));
                    }
                    int minpre = 0x3f3f3f3f;
                    if (left) {
                        for (int k = j + len; k < j + 2 * len;
                             k += max(1, len / 2)) {
                            minpre = min(minpre, dp[i - 1][k]);
                        }
                    } else {
                        for (int k = j - len; k < j; k += max(1, len / 2)) {
                            minpre = min(minpre, dp[i - 1][k]);
                        }
                    }
                    dp[i][j] = minpre + base;
                    left = !left;
                }
                /*
                for (int k = 0; k < l; k++) {
                    cout << dp[i][k] << ' ';
                }
                cout << endl;
                */
            }
            cout << min(dp[n][0], dp[n][l / 2]) << endl;
        }
        return 0;
    }
    

    E. Directing Edges

    大意:

    给出n个点m条边的图,其中有的边为有向的,有的边为无向的,现在要求确定每个无向边的方向,使得最后获得的图中没有有向环。

    思路:

    对有向边进行拓扑排序,如果有环,那么必然无解

    否则必然有解,因为可以将所有的无向边的方向设置为从拓扑序小的指向拓扑序大的,这样保证没有环

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    int t, n, m, in[N];
    struct node {
        int u, v;
    } edge[N];
    vector<int> mp[N];
    int cnt, vis[N];
    void bfs() {
        queue<int> q;
        for (int i = 1; i <= n; i++) {
            if (in[i] == 0) q.push(i);
        }
        while (!q.empty()) {
            int now = q.front();
            q.pop();
            vis[now] = ++cnt;
            for (int i = 0; i < mp[now].size(); i++) {
                int ne = mp[now][i];
                in[ne]--;
                if (in[ne] == 0) q.push(ne);
            }
        }
    }
    
    int main() {
        cin >> t;
        while (t--) {
            cin >> n >> m;
            for (int i = 1; i <= n; i++) {
                in[i] = vis[i] = 0;
                mp[i].clear();
            }
            for (int i = 0; i < m; i++) {
                int p, x, y;
                cin >> p >> x >> y;
                if (p) mp[x].push_back(y), in[y]++;
                edge[i] = {x, y};
            }
            cnt = 0;
            bfs();
            if (cnt == n) {
                cout << "YES" << endl;
                for (int i = 0; i < m; i++) {
                    int u = edge[i].u, v = edge[i].v;
                    if (vis[u] < vis[v])
                        cout << u << ' ' << v << endl;
                    else
                        cout << v << ' ' << u << endl;
                }
            } else
                cout << "NO" << endl;
        }
        return 0;
    }
    

    F. Removing Leaves

    大意:

    给出n个点的树,每次可以选择k个父节点相同的叶子,然后删掉他们,问一共能删几次

    思路:

    类似拓扑排序的方法,每次选择度为1的节点删掉,然后记录父节点删掉子节点的数量,如果父节点删掉的数量等于k,那么答案就+1

    注意如果父节点删掉k个,且此时度为1,就要将其入队

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    int t, n, k;
    vector<int> mp[N];
    int in[N], del[N], res;
    int vis[N];
    void bfs() {
        queue<int> q;
        for (int i = 1; i <= n; i++) {
            if (in[i] == 1) q.push(i);
        }
        while (!q.empty()) {
            int now = q.front();
            q.pop();
            vis[now] = 1;
            for (int i = 0; i < mp[now].size(); i++) {
                int ne = mp[now][i];
                if (vis[ne]) continue;
                in[ne]--;
                del[ne]++;
                if (del[ne] == k) {
                    del[ne] = 0;
                    res++;
                    if (in[ne] == 1) q.push(ne);
                }
            }
        }
    }
    
    int main() {
        cin >> t;
        while (t--) {
            cin >> n >> k;
            for (int i = 1; i <= n; i++) {
                mp[i].clear();
                in[i] = del[i] = vis[i] = 0;
            }
            for (int i = 1; i < n; i++) {
                int x, y;
                cin >> x >> y;
                mp[x].push_back(y);
                mp[y].push_back(x);
                in[x]++;
                in[y]++;
            }
            res = 0;
            bfs();
            cout << res << endl;
        }
        return 0;
    }
    

    G. Columns Swaps

    大意:

    给出一个2xn的矩阵,问能否通过交换某几列的第一行和第二行,使得第一行和第二行都是1到n的全排列

    思路:

    首先统计1到n出现的次数,必须都是两次否则输出-1

    然后利用拓展域并查集,i代表这一列不换,i+n代表这一列需要变换

    这样如果某个数出现在同一行,假设出现的位置分别为i和j,那么合并i和j+n,以及i+n和j

    否则合并i和j i+n和j+n

    这样最后会出现很多小联通块,这时候就选择i和i+n中数量较小的那一个即可

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 2e5 + 5;
    typedef long long LL;
    int t;
    int a[N][2], n, cnt[N], pre[N], Size[2 * N], vis[2 * N], res[N], rescnt;
    int f[2 * N];
    int findf(int x) { return x == f[x] ? x : f[x] = findf(f[x]); }
    void Union(int x, int y) {
        int fx = findf(x), fy = findf(y);
        if (fx != fy) {
            f[fx] = fy;
            Size[fy] += Size[fx];
        }
    }
    int main() {
        cin >> t;
        while (t--) {
            cin >> n;
            for (int i = 1; i <= n; i++) cnt[i] = 0, pre[i] = 0;
            for (int i = 1; i <= n; i++) cin >> a[i][0], cnt[a[i][0]]++;
            for (int i = 1; i <= n; i++) cin >> a[i][1], cnt[a[i][1]]++;
            int flag = 1;
            for (int i = 1; i <= n; i++)
                if (cnt[i] != 2) {
                    flag = 0;
                }
            if (flag == 0) {
                printf("-1
    ");
                continue;
            }
            for (int i = 1; i <= n; i++) {
                f[i] = i, f[i + n] = i + n;
                Size[i] = 0, Size[i + n] = 1;
                vis[i] = vis[i + n] = 0;
            }
            for (int i = 0; i < 2; i++) {
                for (int j = 1; j <= n; j++) {
                    int now = a[j][i];
                    if (pre[now] == 0)
                        pre[now] = j;
                    else {
                        if (pre[now] == j) continue;
                        int k = pre[now];
                        if (a[k][i] == now) {  //同一行
                            int fx = findf(k), fy = findf(j);
                            int fx2 = findf(k + n), fy2 = findf(j + n);
                            if (fx == fy)
                                flag = 0;
                            else
                                Union(fx, fy2), Union(fx2, fy);
                        } else {
                            int fx = findf(k), fy = findf(j);
                            int fx2 = findf(k + n), fy2 = findf(j + n);
                            if (fx == fy2)
                                flag = 0;
                            else
                                Union(fx, fy), Union(fx2, fy2);
                        }
                    }
                }
            }
            for (int i = 1; i <= n; i++)
                if (findf(i + n) == findf(i)) {
                    flag = 0;
                    break;
                }
            if (flag == 0) {
                printf("-1
    ");
                continue;
            }
            for (int i = 1; i <= n; i++) {
                int x = findf(i), y = findf(i + n);
                // if (x == i && y == (i + n)) continue;
                if (!vis[x] && !vis[y]) {
                    if (Size[x] > Size[y])
                        vis[y] = 1;
                    else
                        vis[x] = 1;
                }
            }
            rescnt = 0;
            for (int i = 1; i <= n; i++) {
                if (vis[f[i + n]]) res[rescnt++] = i;
            }
            printf("%d
    ", rescnt);
            for (int i = 0; i < rescnt; i++) printf("%d ", res[i]);
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    生活中头疼脑热及医生诊断用药相关,持续更新
    python3 面试题 英文单词全部都是以首字母大写,逐个反转每个单词
    python 代码如何打包成.exe文件(Pyinstaller)
    charles使用
    经典bug
    python3面试-查找字符串数组中的最长公共前缀
    python3面试题 按规律写出下一个数1,11,21,1211,111221
    python3 测试的时候如何批量随机生成伪数据?(faker模块的)
    python3面试题-一个包含n个整数的数组a,判断a中是否存在三个元素,a,b,c,使得a+b+c=0
    python3面试-将N(N<10000)个人排成一排,从第1个人开始报数;如果报数是M的倍数就出列
  • 原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14368872.html
Copyright © 2011-2022 走看看