第 369 场周赛(简单位运算,分类讨论,dfs,树形dp)

发布时间 2023-10-29 15:28:37作者: 深渊之巅

 简单位运算模拟

class Solution {
public:
    int findKOr(vector<int>& nums, int k) {
        vector<int> bit(32, 0);
        for(int i = 0; i < 31; i ++ ) {
            int cnt = 0;
            for(auto x: nums) {
                if(x >> i & 1) cnt ++ ;
            }
            if(cnt >= k) bit[i] = 1;
        }
        
        int res = 0;
        for(int i = 0; i < 31; i ++ ) {
            if(bit[i]) res += 1 << i;
        }
        
        return res;
    }
};

 

 分类讨论问题

class Solution {
public:
    long long minSum(vector<int>& nums1, vector<int>& nums2) {
        long long sum1 = 0, sum2 = 0;
        int cnt1 = 0, cnt2 = 0;
        
        for(auto x: nums1) {
            sum1 += x;
            if(x == 0) cnt1 ++ ;
        }
        
        for(auto x: nums2) {
            sum2 += x;
            if(x == 0) cnt2 ++ ;
        }
        
        
        if(sum1 > sum2) {
            if(sum2 + cnt2 > sum1 && cnt1 == 0 || cnt2 == 0) return -1;
            return max(sum1 + cnt1, sum2 + cnt2);
        } else if(sum1 < sum2){
            if(sum1 + cnt1 > sum2 && cnt2 == 0|| cnt1 == 0) return -1;
           return max(sum1 + cnt1, sum2 + cnt2);
        } else {
            if(cnt1 == cnt2) return sum1 + cnt1;
            if(cnt1 == 0 || cnt2 == 0) return -1;
            return sum1 + max(cnt1, cnt2);
        }
        
    }
};

 

 

 动态规划: f[i]表示以i为结尾的使得前i个元素变为美丽数组需要执行的最小递增运算数且第i项大于等于k。

f[i]  = max(0, k - nums[i]) + min(f[i - 1], f[i - 2], f[i - 3])

class Solution:
    def minIncrementOperations(self, nums: List[int], k: int) -> int:
        n = len(nums)
        f = [0] * n
        for i in range(3):
            f[i] = max(0, k-nums[i])
        for i in range(3, n):
            f[i] = min(f[i-3:i]) + max(0, k-nums[i])
        return min(f[-3:])

 

 

 方法一:dfs

状态转移: 每一次向下递归都有选择方法一和方法二两种方向

class Solution:
    def maximumPoints(self, edges: List[List[int]], coins: List[int], k: int) -> int:
        n = len(coins)
        g = [[] for _ in range(n)]
        for u, v in edges:
            g[u].append(v)
            g[v].append(u)
            
        @cache
        def dfs(u, fa, time):
            if time > 15:
                return 0
       # 方案1 res1
= (coins[u] >> time) - k for x in g[u]: if x != fa: res1 += dfs(x, u, time) # 方案2 time += 1 res2 = (coins[u] >> time) for x in g[u]: if x != fa: res2 += dfs(x, u, time)
        # 两个方案取得最大值
return max(res1, res2) return dfs(0, -1, 0)
const int K = 20;

class Solution {
public:
    int maximumPoints(vector<vector<int>>& edges, vector<int>& val, int m) {
        int n = edges.size() + 1;
        vector<vector<int>> a(n);
        for (auto& e : edges) {
            int x = e[0], y = e[1];
            a[x].push_back(y);
            a[y].push_back(x);
        }
        vector<vector<int>> dp(n, vector<int>(K, -1));
        function<int(int, int, int)> solve = [&](int u, int parent, int k) {
            int& ret = dp[u][k];
            if (ret >= 0) return ret;
            ret = 0;
            // 方案1
            int cur = (val[u] >> k) - m;
            for (auto& v : a[u]) {
                if (v == parent) continue;
                cur += solve(v, u, k);
            }
            ret = max(ret, cur);
            //方案2
            if (k + 1 < K) {
                int cur = val[u] >> (k + 1);
                for (auto& v : a[u]) {
                    if (v == parent) continue;
                    cur += solve(v, u, k + 1);
                }
                ret = max(ret, cur);
            }
            return ret;
        };
        int ret = solve(0, -1, 0);
        return ret;
    }
};