美文网首页
5700. 使所有区间的异或结果为零

5700. 使所有区间的异或结果为零

作者: 来到了没有知识的荒原 | 来源:发表于2021-03-07 21:19 被阅读0次

5700. 使所有区间的异或结果为零

这个dp有点难想

wnj大佬(喂你脚下有坑)视频题解
吴自华题解

关于复杂度
首先代码到计算新的,复杂度已经有O(k * MAXV)
到计算已经有的group[i]里存的数和外面的遍历k结合,实际上访问了N次,也可以理解为内外两层for刚好把N个数遍历完,因此这一部分复杂度是O(N * MAXV)

总复杂度为两部分加和O(k * MAXV) + O(N * MAXV)

class Solution {
public:
    int minChanges(vector<int> &nums, int k) {
        const int MAXV = 1024;
        const int INF = 0x3f3f3f3f;
        int n = nums.size();

        vector<int> size(k);  // 统计这一列总共多少数
        vector<unordered_map<int, int>> group(k + 1);  // 统计这一列每个数出现的次数

        for (int i = 0; i < n; i++) {
            group[i % k][nums[i]]++;
            size[i % k]++;
        }
        int dp[k + 1][MAXV];
        memset(dp, 0x3f, sizeof dp);
        dp[0][0] = 0;

        // dp[i][v]: 前i个数,异或和为v所要改的数最小值

        // 状态转移方程:
        // dp[i][v^s]=dp[i-1][v]+cost(s);
        // s是要改成的数
        // 当s是这一列全新的数的时候,cost(s)=size[i] (i是这一列)
        // 当s是这一列已经有的数的时候,cost(s)=size[i]-freq(s) (freq(s)是s在这一列出现的次数)
        for (int i = 1; i <= k; i++) {
            // 改成新的
            int mn = INF;
            for (int j = 0; j < MAXV; j++)mn = min(mn, dp[i - 1][j]);
            for (int j = 0; j < MAXV; j++)dp[i][j] = mn + size[i - 1];

            // 改成已存在的
            for (auto p:group[i - 1]) {
                for (int v = 0; v < MAXV; v++) {
                    int s = p.first, freq = p.second;
                    dp[i][s ^ v] = min(dp[i][s ^ v], dp[i - 1][v] + size[i - 1] - freq);
                }
            }
        }
        return dp[k][0];
    }
};

相关文章

网友评论

      本文标题:5700. 使所有区间的异或结果为零

      本文链接:https://www.haomeiwen.com/subject/eboyqltx.html