3070. 元素和小于等于 k 的子矩阵的数目3069. 将元素分配到两个数组中 I
根据题意模拟即可。
class Solution {
public:
vector<int> resultArray(vector<int>& nums) {
vector<int> a, b;
int n = (int)nums.size();
a.push_back(nums[0]);
b.push_back(nums[1]);
for (int i = 2; i < n; i++) {
if (a.back() > b.back()) a.push_back(nums[i]);
else b.push_back(nums[i]);
}
reverse(b.begin(), b.end());
while (!b.empty()) a.push_back(b.back()), b.pop_back();
return a;
}
};
统计属于Y字母区域的0,1,2的数量,再统计矩阵0,1,2的总数目,然后枚举Y型区域全为0,1,2,枚举矩形除Y型区域外全为0,1,2(两者不相等)。然后维护最小值即可。
class Solution {
public:
int minimumOperationsToWriteY(vector<vector<int>>& grid) {
int ans = 1e9;
//a维护矩形0,1,2的数目
//b维护Y型区域0,1,2的数目
vector<int> a(3, 0), b(3, 0);
int n = grid.size();
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
a[grid[i][j]] += 1;
int x = 0, y = 0;
while (x <= n / 2 && y <= n / 2) b[grid[x][y]]++, x++, y++;
x--,y--;
while (y < n) b[grid[x][y]]++, x--,y++;
x = n / 2, y = n / 2;
while(x < n) b[grid[x][y]]++, x++;
//最中间的矩形块多算了两遍 所以减2
b[grid[n / 2][n / 2]] -= 2;
//枚举Y型区域和矩形区域的数字是多少
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++)
if (i != j) {
//Y型区域改成b[i]为:b[0] + b[1] + b[2] - b[i]
//矩形以外的区域改成a[j]为:a[0] + a[1] + a[2] - (b[0] + b[1] + b[2]) - (a[j] - b[j])
//两者相加
ans = min(ans, - b[i] + a[0] + a[1] + a[2] - a[j] + b[j]);
}
}
return ans;
}
};
维护一个二维前缀和即可。但要注意有一部分贡献会加两遍,所以要减去。
class Solution {
public:
int countSubmatrices(vector<vector<int>>& grid, int k) {
int m = grid.size();
int n = grid[0].size();
int ans = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i > 0) grid[i][j] += grid[i - 1][j];
if (j > 0) grid[i][j] += grid[i][j - 1];
if (i > 0 && j > 0) grid[i][j] -= grid[i - 1][j - 1];
if (grid[i][j] <= k) ans++;
}
}
return ans;
}
只有个数,但值的范围为
~
,所以考虑离散化。维护两个树状数组,用于查询两个arr数组中>x的数量是多少(树状数组查询的是<=x的数,我们维护一个总数量,两者相减就可以得到),然后根据题目题意所求即可。
class Solution {
public:
const int N = 100001;
//两个树状数组
int c1[100010], c2[100010];
int lowbit(int x) {return x &(-x);}
int get_num1(int x)
{
int sum = 0;
for(; x; x -= lowbit(x)) sum += c1[x];
return sum;
}
int get_num2(int x)
{
int sum = 0;
for(; x; x -= lowbit(x)) sum += c2[x];
return sum;
}
void add1(int x)
{
for (; x < N; x += lowbit(x)) c1[x] += 1;
}
void add2(int x)
{
for (; x < N; x += lowbit(x)) c2[x] += 1;
}
vector<int> resultArray(vector<int>& nums) {
//离散化 + 树状数组插入 + 查询
int n = nums.size();
vector<int> ans(n);
//a:离散化数组
vector<int> a;
for (int i = 0; i < n; i++) a.push_back(nums[i]);
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());
//映射后查询下标
auto find = [&](int x)
{
int l = 0, r = a.size() - 1;
while(l < r)
{
int mid = l + r + 1>> 1;
if(x >= a[mid]) l = mid;
else r = mid - 1;
}
return r + 1;//从1开始 树状数组也是从1开始的
};
//用ans来记录答案
int l = 0, r = n - 1;
ans[l++] = nums[0], ans[r--] = nums[1];
add1(find(nums[0])), add2(find(nums[1]));
//记录两个数组的数目,刚开始两个数组的数目都为1
int num1 = 1, num2 = 1;
for (int i = 2; i < n; i++) {
int x = find(nums[i]);
int nums1 = get_num1(x), nums2 = get_num2(x);
//cout << num1 << " " << nums1 << " " << num2 << " " << nums2 << endl;
if (num1 - nums1 > num2 - nums2) {
num1++;
ans[l++] = nums[i];
add1(x);
}
else if (num1 - nums1 < num2 - nums2) {
num2++;
ans[r--] = nums[i];
add2(x);
}
//两者>x的数量相等
else {
if (num1 > num2) {
num2++;
ans[r--] = nums[i];
add2(x);
}
else {
num1++;
ans[l++] = nums[i];
add1(x);
}
}
}
//注意拼接的话arr2数组需要翻转一下
reverse(ans.begin() + l, ans.end());
return ans;
}
};