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;
}
};