zoukankan      html  css  js  c++  java
  • codeforces刷题(五)

    1、Maximum Subsequence Value

    (n)个数中挑(k)个数,使得(sum2^i)最大(将这(k)个数用二进制表示,如果二进制第 (i) 位为1的数的个数多于(max(1,k-2))个,就加上(2^i))。

    题解

    性质:选高位为1的数比选多个低位为1的数更优,(1 + 2^1 + 2^2+···+2^{n-1} <2^n)

    (n>=3)时,(k =3)能取得最大的(sum2^i)。也就是说,当(k>3)时,多选的(k-3)个数不能使得原本第(i)位的0((k =3)时)变为有效的1,既第(i)位全为1,也只有(k-3)个数,小于(max(1,k-2))

    int main()
    {
        int n;
        cin >> n;
    
        long long a[505];
        myfor(i, 1, n) cin >> a[i];
        
        if (n <= 3) {
            long long ans = a[1];
            myfor(i, 1, n) ans |= a[i];
            cout << ans << endl;
        } 
        else {
            long long ans = 0;
            myfor(i, 1, n) myfor(j, i + 1, n) myfor(k, j + 1, n) ans = max(ans, a[i]|a[j]|a[k]);
            cout << ans << endl;
        }
    
        return 0;
    }
    

    2、Solve The Maze

    给一张二维迷宫,出口是((n,m))

    • . 表示这个位置可以行走
    • #表示这个位置是墙
    • G表示这个位置上有一个好人
    • B表示这个位置上有一个坏人

    问是否存在一种方案:在某些位置上放墙,既令(map[i][j] = '#'),使得好人走出迷宫而坏人不能走出迷宫。

    题解

    在坏人的周围都放上墙,然后从出口出发,看是否能走到所有好人所在的位置。

    
    

    3、Tree Shuffling(好题)

    一棵树有(n)个节点,每个节点有三个值:(a)(花费),(b)(已有的值),(c)(想要变成的值)

    操作:在任意一颗子树中选择(k)个节点,然后按照你的意愿排列这(k)个节点

    操作代价:假设这颗子树的根是(u)(operation\_cost = 2 * k * a[u])

    问任意次操作后,将所有的节点的(b)变成(c)的最小代价是多少?

    (b,cin {0,1})

    题解

    贪心,从花费较小的节点开始操作起

    思路比较简单,就是不会写

    pair<ll, ll> DFS(int u, int pa, int cost)  {
        pair<int, int> now;     // 统计这颗子树需要对几个节点进行重新排列
        if (b[u] != c[u]) {
            now.first += b[u];
            now.second += c[u];
        }
        for (int i = head[u]; i != -1; i = e[i].next) {
            int v = e[i].to;
            if (v == pa) continue;
            pair<ll, ll> nex = DFS(v, u, min(cost, a[v]));
            now.first += nex.first;
            now.second += nex.second;
        }
        int cnt = min(now.first, now.second);
        ans += 2ll * cnt * cost;    // cost: root -> u 这条链上的最小花费
        now.first -= cnt;    
        now.second -= cnt;
        return now;
    }
    

    4、Odd-Even Subsequence

    给一个序列(a),从中挑选(k)个数构成序列(s)(不改变数的位置)。定义(x = min(max{s_1,s_3,s_5,s_7,···},max{s_2,s_4,s_6,s_8,···})),问最小的(x)是多少?

    题解

    最小化最大值,考虑二分枚举答案,检查以下两种情况即可,换言之,我们需要构造出这样一个子序列(s)

    • 答案在奇序列中
    • 答案在偶序列中

    我的想法是:假设每次枚举的答案(mid)一定在(a)中(用(mid)构造子序列(s)),然后发现(check)的时候,非常不好做,因为必须判断假设是否成立。

    /*
    不断缩小答案的上界
    */
    bool check(int x) {
        // 答案在偶序列
        for (int i = 1, cnt = 0; i <= n; i++) {
            if (((cnt & 1) && (a[i] <= x)) || (cnt % 2 == 0)) cnt++;    // 构造合适的s(贪心)
            if (cnt >= k) return true;
        }
        // 答案在奇序列
        for (int i = 1, cnt = 0; i <= n; i++) {
            if (((cnt % 2 == 0) && (a[i] <= x)) || (cnt & 1)) cnt++;
            if (cnt >= k) return true;
        }
        return false;
    }
    

    5、AND, OR and square sum

    给一个序列(a),有如下操作:

    • 任选两个数(a_i)(a_j),令(a_i^{'}= a_i & a_j)(a_j^{'} = a_i |a_j)

    可以操作任意次,令(ans = sum_{i = 1}^na_i^{'2}),最大化(ans)

    题解

    假设(x = a_i |a_j),有(x >= a_i)(x >= a_j),所以我们可以让(a)中的最大值不断变大,而(ans)不会变小。按照这个思路有:令(a_1 = a_{max})(按降序排序),有(a_1 = a_1 | a_2)(a_2 = a_1 & a_2)(a_1 = a_1 | a_3)(a_3 = a_1 & a_3)、······、(a_1 = a_1 | a_n)(a_n = a_1 & a_n)。用相同的办法求出(a_2^{'})(a_3^{'}),...,(a_n^{'}),既能求得最大的(ans)

    显然,这样计算需要两次循环,复杂度(O(n^2))。实际上,给出的操作有个性质不会改变每位包含1的个数,既(a_i^{'} = a_i & a_j)(a_j^{'} = a_i | a_j)(a_i) 的二进制位上的 1 给了 (a_j​),但总的1的个数并没有改变。

    所以,我们只需要统计二进制每位有多少个1,然后组成一个个数就行了。

    妙啊,做(cf​)的题始终差那临门一脚!

    int main()
    {
        int x;
        cin >> n;
        myfor(i, 1, n) {
            cin >> x;
            int t = 0;
            while(x) {
                cnt[t++] += x & 1;
                x >>= 1;
            }
        }
    
        ll ans = 0;
        myfor(i, 1, n) {
            ll x = 0;
            myfor(j, 0, 20) if (cnt[j]) {
                x += (1 << j);
                cnt[j]--;
            }
            ans += x * x;
        }
        cout << ans << endl;
    
        return 0;
    }
    
  • 相关阅读:
    B
    给定二叉树先序、中序遍历序列,求后序遍历
    24点游戏dfs求解
    设计模式之单例模式
    生产者—消费者模式示例
    LeetCode(3):Longest Substring Without Repeating Characters
    LeetCode(5):Longest Palindromic Substring
    LeetCode(60):Permutation Sequence
    LeetCode(50):Pow(x,n)
    LeetCode(69):Sqrt(x)
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/13193569.html
Copyright © 2011-2022 走看看