• Codeforces Round #498 (Div. 3) 简要题解


    [比赛链接]

              https://codeforces.com/contest/1006

    [题解]

           Problem A. Adjacent Replacements

           [算法]

                   将序列中的所有偶数替换为奇数即可

                   时间复杂度 : O(N)

           [代码]

                   

    #include<bits/stdc++.h>
    using namespace std;
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    int main()
    {
            
            int n;
            read(n);
            for (int i = 1; i <= n; i++)
            {
                    int x;
                    read(x);
                    if (x & 1) printf("%d ",x);
                    else printf("%d ",x - 1);
            }
            printf("
    ");
            
            return 0;
        
    }

                 Problem B. Polycarp's Practice

                 [算法]

                         要求k天的和最大化 , 我们不妨将这些数加入一个堆中 , 取出前k大值

                         构造一组合法的解即可

                         时间复杂度 : O(NlogN)

                  [代码]

                           

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 2010
    
    int ans[MAXN];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    int main()
    {
            
            int n , k , t = 0 , value = 0;
            static priority_queue< pair<int,int> > q;
            read(n); read(k);
            for (int i = 1; i <= n; i++)
            {
                    int x;
                    read(x);
                    q.push(make_pair(x,i));
            }
            while (t < k)
            {
                    value += q.top().first;
                    ans[++t] = q.top().second;
                    q.pop();        
            }
            sort(ans + 1,ans + k + 1);
            printf("%d
    ",value);
            for (int i = 1; i <= k - 1; i++) printf("%d ",ans[i] - ans[i - 1]);
            printf("%d
    ",n - ans[k - 1]);
            
            return 0;
        
    }

                   Problem C. Three Parts of the Array

                   [算法]

                           用Two Pointers扫描求出答案即可

                           也可以通过std :: set等数据结构求解

                          时间复杂度 : O(N)

                    [代码]

                             

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 2e6 + 10;
    
    long long a[MAXN];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    
    int main()
    {
            
            long long n;
            read(n);
            for (int i = 1; i <= n; i++) read(a[i]);
            long long l = 1 , r = n;
            long long s1 = 0 , s2 = 0 , ans = 0;
            while (l <= r)
            {
                    if (s1 < s2)
                    {
                            s1 += a[l++];
                            if (s1 == s2) ans = s1;        
                    }    else if (s2 < s1)
                    {
                            s2 += a[r--];
                            if (s1 == s2) ans = s1;
                    } else 
                    {
                            if (l == r) break;
                            s1 += a[l++];
                            s2 += a[r--];
                            if (s1 == s2) ans = s1;
                    }
            }
            printf("%I64d
    ",ans);
            
            return 0;
        
    }

                          Problem D. Two Strings Swaps

                          [算法]

                                  枚举字符串的前[n/2]个字符 ([x]表示向下取整) ,

                                  如果字符串a和字符串b的第i个字符和第(n - i + 1)个字符共有4个不同的字符 , 显然对答案产生2的贡献

                                  如果有3个不同字符 , 当字符串a的第i个字符和第(n - i + 1)个字符相同 , 则对答案产生2的贡献 , 否则对答案产生1的贡献

                                  如果有2个不同字符 , 如果第a的第i个字符出现次数不为2 , 则对答案产生1的贡献

                                  当字符串长度为奇数时 , 若字符串a的第(n + 1) / 2和字符串b的第(n + 1) / 2个字符不相等 , 则对答案产生1的贡献

                          [代码]

                                   

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e5 + 10;
    
    int n , ans;
    char a[MAXN],b[MAXN];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    int main()
    {
            
            scanf("%d",&n);
            scanf("%s%s",a + 1,b + 1);
            for (int i = 1; i <= n / 2; i++)
            {
                    map< char,int > mp;
                    mp.clear();
                    mp[a[i]]++;
                    mp[a[n - i + 1]]++;
                    mp[b[i]]++;
                    mp[b[n - i + 1]]++;
                    if ((int)mp.size() == 4) ans += 2;
                    if ((int)mp.size() == 3)
                    {
                            if (a[i] == a[n - i + 1]) ans += 2;
                            else ans++;
                    }
                    if ((int)mp.size() == 2)
                    {
                            if (mp[a[i]] != 2)
                                ans++;
                    }
            }
            if ((n & 1) && a[n / 2 + 1] != b[n / 2 + 1]) ans++;
            printf("%d
    ",ans);
            
            return 0;
        
    }

                               Problem E. Military Problem

                               [算法]

                                       不妨先求出整棵树的DFS序 , 记为Dfn[] 

                                       然后 , 我们用Pos[i]表示DFS序为i的节点

                                       对于询问(ui , ki) ,  显然 , 答案为Pos[Dfn[ui] - 1 + k] 

                                       时间复杂度 : O(N)

                              [代码]

                                      

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 2e5 + 10;
    
    int n , q , timer;
    int size[MAXN],ans[MAXN],depth[MAXN],dfn[MAXN];
    vector< int > G[MAXN];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void dfs(int u)
    {
            size[u] = 1;
            dfn[u] = ++timer;
            ans[timer] = u;
            for (unsigned i = 0; i < G[u].size(); i++)
            {
                    depth[G[u][i]] = depth[u] + 1;
                    dfs(G[u][i]);
                    size[u] += size[G[u][i]];
            }
    }
    
    int main()
    {
            
            read(n); read(q);
            for (int i = 2; i <= n; i++)
            {
                    int x;
                    read(x);
                    G[x].push_back(i);
            }
            dfs(1);
            while (q--)
            {
                    int u , k;
                    read(u); read(k);
                    if (size[u] < k)
                    {
                            printf("-1
    ");
                            continue;
                    }
                    printf("%d
    ",ans[dfn[u] + k - 1]);        
            }
            
            return 0;
        
    }

                                 Problem F. Xor Paths

                                 [算法]

                                         显然 , 所有的路径长度都为(n + m - 1)

                                         考虑使用Meet-In-The-Middle( 中途相遇法 )

                                         第一遍DFS求出前(n + m - 1)步 , 每个位置上出现的异或和情况数

                                         第二遍DFS求出后(n + m) / 2步 , 根据第一遍DFS求出的情况数统计答案

                                         时间复杂度 : O(2 ^ ((n + m - 2) / 2) * (n + m - 2) / 2)

                             [代码]

                                     

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 25
    #define MAXS 100005
    
    int n , m;
    long long a[MAXN][MAXN];
    long long val , ans = 0;
    map< long long,int > cnt[MAXN][MAXN];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline bool valid(int x,int y)
    {
            return x >= 1 && x <= n && y >= 1 && y <= m;
    }
    inline void dfs1(int x,int y,int step,long long k)
    {
            if (step == (n + m - 1) / 2)
            {
                    cnt[x][y][k]++;
                    return;
            }
            if (valid(x + 1,y)) dfs1(x + 1,y,step + 1,k ^ a[x + 1][y]);
            if (valid(x,y + 1)) dfs1(x,y + 1,step + 1,k ^ a[x][y + 1]);
    }
    inline void dfs2(int x,int y,int step,long long k)
    {
            if (step == (n + m) / 2)
            {
                    if (valid(x,y - 1)) ans += cnt[x][y - 1][val ^ k];
                    if (valid(x - 1,y)) ans += cnt[x - 1][y][val ^ k];
                    return;
            }
            if (valid(x - 1,y)) dfs2(x - 1,y,step + 1,k ^ a[x - 1][y]);
            if (valid(x,y - 1)) dfs2(x,y - 1,step + 1,k ^ a[x][y - 1]);
    }
    
    int main()
    {
            
            read(n); read(m); read(val);
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= m; j++)
                    {
                            read(a[i][j]);
                    }
            }
            if (n == 1 && m == 1)
            {
                    if (a[1][1] == val) printf("1
    ");
                    else printf("0
    ");
                    return 0;
            }
            dfs1(1,1,1,a[1][1]);
            dfs2(n,m,1,a[n][m]); 
            printf("%I64d
    ",ans);
            
            return 0;
        
    }

     

  • 相关阅读:
    查看CLOUD系统级IIS日志
    采购订单设置采购部门为缺省值
    单据头数据复制到单据体
    CLOUD设置过滤方案不共享
    BZOJ 4773: 负环 倍增Floyd
    LOJ #539. 「LibreOJ NOIP Round #1」旅游路线 倍增floyd + 思维
    BZOJ 4821: [Sdoi2017]相关分析 线段树 + 卡精
    一些常用公式/技巧
    BZOJ 4517: [Sdoi2016]排列计数 错排 + 组合
    BZOJ 3162: 独钓寒江雪 树的同构 + 组合 + 计数
  • 原文地址:https://www.cnblogs.com/evenbao/p/9734944.html
Copyright © 2020-2023  润新知