zoukankan      html  css  js  c++  java
  • Codeforces Round #715 (Div. 2)

    Codeforces Round #715 (Div. 2)

    A Average Height

    题目

    给定(n)个数,将他们重新排列,使得若一对相邻数的平均数为整数,则称它们上镜,求上镜数最大值对应的重排方案.

    思路

    显然,奇数放一堆,偶数放一堆.

    代码

    #include <iostream>
    #include <cstdio>
    #include <vector>
    using namespace std;
    int read() {
        int re = 0;
        char c = getchar();
        bool negt = false;
        while(c < '0' || c > '9')
            negt |= (c == '-')  , c = getchar();
        while(c >= '0' && c <= '9')
            re = (re << 1) + (re << 3) + c - '0' , c = getchar();
        return negt ? -re : re;
    }
    template <char l , char r>
    char readc() {
        char c = getchar();
        while(c < l || c > r)c = getchar();
        return c;
    }
    
    int n;
    vector <int> a[2];
    void solve() {
        a[0].clear() , a[1].clear();
        n = read();
        for(int i = 1 ; i <= n ; i++) {
            int tmp = read();
            a[tmp & 1].push_back(tmp);
        }
        for(int i : a[1])a[0].push_back(i);
        for(int i : a[0])printf("%d " , i);
        putchar('
    ');
    }
    int main() {
        int T = read();
        while(T--)solve();
        return 0;
    }
    

    B TMT Document

    题目

    给定一个由T,M构成的字符串,将它划分为若干个不相交的子序列,使得所有子序列都等于TMT,问有没有解.

    思路

    猜到的一个结论.

    T的数量不是M的数量,答案为NO.

    若从前往后扫一遍,某时刻M的数量大于T的数量,答案为NO.

    若从前往后扫一遍,某时刻M的数量大于T的数量,答案为NO.

    若以上三个均不满足,答案为YES.

    证明:?

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <stack>
    using namespace std;
    int read() {
        int re = 0;
        char c = getchar();
        bool negt = false;
        while(c < '0' || c > '9')
            negt |= (c == '-')  , c = getchar();
        while(c >= '0' && c <= '9')
            re = (re << 1) + (re << 3) + c - '0' , c = getchar();
        return negt ? -re : re;
    }
    template <char l , char r>
    char readc() {
        char c = getchar();
        while(c < l || c > r)c = getchar();
        return c;
    }
    
    const int N = 1e5 + 10;
    int n;
    int s[N];
    bool flag[N];
    stack <int> stk;
    void solve() {
        n = read();
    
        for(int i = 1 ; i <= n ; i++)s[i] = readc<'A' , 'Z'>();
        int m = 0 , t = 0;
        for(int i = 1 ; i <= n ; i++)m += (s[i] == 'M') , t += (s[i] == 'T');
        if(m * 2 != t) {
            puts("NO");
            return ;
        }
        m = 0 , t = 0;
        for(int i = 1 ; i <= n ; i++) {
            m += (s[i] == 'M') , t += (s[i] == 'T');
            if(m > t) {
                puts("NO");
                return ;
            }
        }
        m = 0 , t = 0;
        for(int i = n ; i > 0 ; i--) {
            m += (s[i] == 'M') , t += (s[i] == 'T');
            if(m > t) {
                puts("NO");
                return ;
            }
        }
        puts("YES");
        return ;
    }
    int main() {
        int T = read();
        while(T--)solve();
        return 0;
    }
    

    C The Sports Festival

    题目

    给定长度为 (n) 的序列 (s),你可以改变序列 (s) 的顺序,求

    [sum_{i=1}^n(max_{j=1}^is_j-min_{j=1}^is_j) ]

    的最小值。

    (1leq nleq2 imes10^3;1leq s_ileq10^9;)

    思路

    我们先对(s)进行排序.

    一个想法是如果已经将(s_{lsim r})放入重排数组,那么重排数组的下一个数是(s_{l-1})(s_{r+1}),自己证.

    一开始还在想枚举第一个数,贪心生成重排数组,然后发现根本找不到一个正确的贪心策略.

    然后通过某种途径这题可以用DP处理.

    (f_{i,j})表示我们已经将(s_{isim j})放入重排数组中的最小的那啥那啥(上面的数学公式),

    根据上面的结论,我们容易得到转移:

    if(i == j)f[i][j] = 0;
    else f[i][j] = min(
    	f[i + 1][j] + a[j] - a[i],
    	f[i][j - 1] + a[j] - a[i]
    ) ;
    

    注意我们已经排序了,所以最小最大值分别是(s_i,s_j)(对应代码中的(a_i,a_j))

    我真菜

    代码

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    
    #define int long long
    using namespace std;
    int read() {
        int re = 0;
        char c = getchar();
        bool negt = false;
        while(c < '0' || c > '9')
            negt |= (c == '-')  , c = getchar();
        while(c >= '0' && c <= '9')
            re = (re << 1) + (re << 3) + c - '0' , c = getchar();
        return negt ? -re : re;
    }
    template <char l , char r>
    char readc() {
        char c = getchar();
        while(c < l || c > r)c = getchar();
        return c;
    }
    
    const int N = 2010;
    int n;
    int a[N];
    int sum[N];
    
    int f[N][N];
    void solve() {
        n = read();
        for(int i = 1 ; i <= n ; i++)
            a[i] = read();
        sort(a + 1 , a + n + 1);
        for(int i = n ; i > 0 ; i--)
            for(int j = i ; j <= n ; j++) {
                if(i == j)f[i][j] = 0;
                else f[i][j] = min(
                    f[i + 1][j] + a[j] - a[i],
                    f[i][j - 1] + a[j] - a[i]
                ) ;
            }
        cout << f[1][n];
    }
    signed main() {
        solve();
        return 0;
    }
    
    

    D Binary Literature

    题目

    给你一个正整数 (n) 和三个长度为 (2 imes n) 的 01 字符串 (s_1,s_2,s_3)。你需要构造一个 01 字符串 (S),使得:

    • 字符串 (S) 的长度不能超过 (3 imes n)
    • (s_1,s_2,s_3) 当中至少有两个字符串是 (S) 的子序列。

    可以证明一定有解,有多种解时输出任意一种即可。(T) 组数据。

    (1leq Tleq10^4;1leq n,sum nleq10^5;)

    思路

    我们仔细想想为什么一定有解,如果能证出来这题也就基本切了.

    想几个问题:

    1. 为什么是三个01串而不是两个.
    2. 为什么(s)的长度为(2n),(S)的长度为(3n).

    第一个问题的反例很容易找到,如果他给一个全是0的串和一个全是1的串,至少要(4n)的长度才能构造出(S).

    但是一但我们有了第三个字符串,就不一样了.

    如果第三个字符串0的个数多,我们就可以补0使得全是0的字符串成为子序列,1的个数多同理.

    最坏情况下,补完后长度是(3n).

    然后,我们顺理成章地想到在三个字符串中选出两个,暂时重命名为(a,b)串,使得两个串中0的同时数量大于等于(n)1的数量同时大于等于(n).(显然,一定可以选出来)

    如果0的数量多,我们就往全是0的串里插1,使得(a,b)是子序列.

    否则,就往1里面插0.

    由于至少有(n)个字符是(a,b)共用的,所以长度不超过(3n).

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int read() {
        int re = 0;
        char c = getchar();
        bool negt = false;
        while(c < '0' || c > '9')
            negt |= (c == '-')  , c = getchar();
        while(c >= '0' && c <= '9')
            re = (re << 1) + (re << 3) + c - '0' , c = getchar();
        return negt ? -re : re;
    }
    template <char l , char r>
    char readc() {
        char c = getchar();
        while(c < l || c > r)c = getchar();
        return c;
    }
    
    const int N = 3e5;
    int n;
    char s[5][N];
    int zero[5];
    char ans[N * 2];
    int fol[N];
    void solve() {
    	memset(zero , 0 , sizeof(zero));
        int rev = false;
        n = read();
        
        for(int i = 0 ; i <= n * 3 ; i++)
        	ans[i] = 0 , fol[i] = 0;
        	
        for(int i = 1 ; i <= 3 ; i++)
            for(int j = 1 ; j <= n * 2 ; j++)
                s[i][j] = readc<'0' , '1'>() , zero[i] += (s[i][j] == '0');
        char *p , *q;
        p = q = NULL;
        for(int i = 1 ; i <= 3 ; i++)
            if(zero[i] >= n) {
                if(p == NULL)p = s[i];
                else q = s[i];
            }
        if(q == NULL) {
        	p = q = NULL;
            for(int i = 1 ; i <= 3 ; i++)
                if(zero[i] <= n) {
                    if(p == NULL)p = s[i];
                    else q = s[i];
                }
            rev = true;
            for(int i = 1 ; i <= n * 2 ; i++)
                p[i] ^= 1 , q[i] ^= 1;
        }
        int z = 0;
        for(int i = 1 ; i <= n * 2 ; i++) {
            if(p[i] == '1')++fol[z];
            else ++z;
        }
        z = 0;
        for(int i = 1 ; i <= n * 2 ; i++) {
            if(q[i] == '1')++fol[z];
            else ++z;
        }
        int cnt = 0;
        while(fol[0])ans[++cnt] = '1' , --fol[0];
        for(int i = 1 ; i <= n * 2 ; i++) {
            ans[++cnt] = '0';
            while(fol[i])ans[++cnt] = '1' , --fol[i];
        }
        for(int i = 1 ; i <= n * 3 ; i++)
            if(ans[i] >= 48)putchar(rev ^ ans[i]);
            else break;
        putchar('
    ');
    }
    int main() {
        int T = read();
        while(T--)solve();
        return 0;
    }
    
  • 相关阅读:
    【HDU2050】折线分割平面
    【Codevs1183】泥泞的道路
    Pair
    【Poj 1832】连环锁
    【Poj1090】Chain
    【UVa 10881】Piotr's Ants
    【Codeforces】665E Beautiful Subarrays
    【T^T】【周赛】第一周周赛——欢迎16级的新同学
    【OI新闻】2016.10.09
    二分图的最大匹配
  • 原文地址:https://www.cnblogs.com/dream1024/p/15542777.html
Copyright © 2011-2022 走看看