leetcode第 103 场双周赛

A K 个元素的最大和

在这里插入图片描述
在这里插入图片描述

显然每次选数组中的最大值能得到最大得分

class Solution {
public:
    int maximizeSum(vector<int> &a, int k) {
        int mx = *max_element(a.begin(), a.end());
        return (mx + mx + k - 1) * k / 2;
    }
};

B 找到两个数组的前缀公共数组

在这里插入图片描述

因为数据量很小,所以直接暴力枚举~

class Solution {
public:
    vector<int> findThePrefixCommonArray(vector<int> &A, vector<int> &B) {
        int n = A.size();
        vector<int> res(n), vis1(n + 1), vis2(n + 1);
        for (int i = 0; i < n; i++) {
            vis1[A[i]] = 1;
            vis2[B[i]] = 1;
            int t = 0;
            for (int j = 1; j <= n; j++)
                if (vis1[j] && vis2[j])
                    t++;
            res[i] = t;
        }
        return res;
    }
};

C 网格图中鱼的最大数目

在这里插入图片描述

求各个非零连通块的和的最大值

class Solution {
public:
    int findMaxFish(vector<vector<int>> &g) {
        int m = g.size(), n = g[0].size();
        int vis[m][n];
        memset(vis, 0, sizeof(vis));
        int res = 0;
        int dr[4] = {1, -1, 0, 0};
        int dc[4] = {0, 0, 1, -1};
        queue<pair<int, int>> q;
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++) {
                if (g[i][j] == 0 || vis[i][j])
                    continue;
                int t = 0;
                q.emplace(i, j);
                vis[i][j] = 1;
                while (!q.empty()) {
                    auto [r, c] = q.front();
                    t += g[r][c];
                    q.pop();
                    for (int k = 0; k < 4; k++) {
                        int nr = r + dr[k];
                        int nc = c + dc[k];
                        if (nr < 0 || nr >= m || nc < 0 || nc >= n || g[nr][nc] == 0 || vis[nr][nc])continue;
                        vis[nr][nc] = 1;
                        q.emplace(nr, nc);
                    }
                    res = max(res, t);
                }
            }
        return res;
    }
};

D 将数组清空

在这里插入图片描述

树状数组:设a[i]的操作次数为p[i],有p[i]=max{ max{ p[j] | a[j]<a[i]&&j<i }, 1+max{ p[j] | a[j]<a[i]&&j>i } },所以我们按元素大小升序枚举a[i]计算p[i],同时用树状数组维护前缀和后缀上的最大值

class Solution {
public:
    vector<int> tr1, tr2;//树状数组
    int n;

    inline int lowbit(int x) {
        return x & -x;
    }

    void update1(int loc, int d) {//前缀更新
        while (loc <= n) {
            tr1[loc] = max(tr1[loc], d);
            loc += lowbit(loc);
        }
    }

    int q1(int loc) {//前缀最大值
        int res = 0;
        while (loc) {
            res = max(res, tr1[loc]);
            loc -= lowbit(loc);
        }
        return res;
    }

    void update2(int loc, int d) {//经过翻转的后缀更新
        while (loc <= n) {
            tr2[loc] = max(tr2[loc], d);
            loc += lowbit(loc);
        }
    }

    int q2(int loc) {//经过翻转的后缀最大值
        int res = 0;
        while (loc) {
            res = max(res, tr2[loc]);
            loc -= lowbit(loc);
        }
        return res;
    }

    long long countOperationsToEmptyArray(vector<int> &a) {
        n = a.size();
        tr1 = vector<int>(n + 1);
        tr2 = vector<int>(n + 1);
        vector<int> o = a;
        iota(o.begin(), o.end(), 0);
        sort(o.begin(), o.end(), [&](int x, int y) { return a[x] < a[y]; });//得到基于升序的下标
        long long res = 0;
        for (int i = 0; i < n; i++) {
            int l = q1(o[i] + 1);// max{ p[j] | a[j]<a[o[i]]&&j<o[i] }
            int r = q2(n + 1 - (o[i] + 1));//max{ p[j] | a[j]<a[o[i]]&&j>o[i] }
            int t = max(l, r + 1);
            res += t;
            update1(o[i] + 1, t);//下标1~n
            update2(n + 1 - (o[i] + 1), t);//下标1~n翻转至n~1
        }
        return res;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值