条件前缀|同余优化|栈
对于利用栈的单调性 可以进行分割 在pop push中处理一部分数据
最后栈中剩余的可再 统一统计一次
lc1856
单增栈帮助找 每个元素作为子数组最小值的左右边界
计算其对应子数组和的乘积
attention: 从后往前统一处理剩余
typedef long long ll;
const int mod = 1e9 + 7;
class Solution {
public:
int maxSumMinProduct(vector<int>& nums) {
int n = nums.size();
vector<ll> p(n + 1, 0);
for (int i = 1; i <= n; ++i)
p[i] = p[i - 1] + nums[i - 1];
ll ret = 0;
// upper stack
stack<int> st;
// 每个元素作为最小值
for (int i = 0; i < n; ++i) {
// 维护单调栈,找到左边第一个比当前元素小的位置
while (!st.empty() && nums[st.top()] > nums[i]) {
int mid = st.top();
st.pop();
//cur_min cal
int l = st.empty() ? 0 : st.top() + 1;
ll sum = p[i] - p[l];
ret = max(ret, sum * nums[mid]);
}
st.push(i); //当前元素不是最小值了,无法计算,入栈
}
// 处理栈剩余
while (!st.empty()) {
int mid = st.top();
st.pop();
//出栈计算,从后到前,nums越来越小,但前缀和可能会越来越大~
int l = st.empty() ? 0 : st.top() + 1;
ll sum = p[n] - p[l];//更大的话,就不会被删,最后再从后往前的从n开始算前缀和
ret = max(ret, sum * nums[mid]);
}
return ret % mod;
}
};
lc1541
栈跟踪左,遍历过程中处理右的连续匹配与缺失
最后补充栈中剩余左所需的右
统计出使括号字符串平衡的最少插入次数
class Solution {
public:
int minInsertions(string s)
{
int n = s.size();
int ret = 0;
stack<char> st;
for (int i = 0; i < n; ++i) {
if (s[i] == '(')
st.push('(');
else
{
// 处理右
if (i < n - 1 && s[i + 1] == ')')
i++; // 跳过下一个右括号
else
ret++; //缺少一个右
// 尝试左
if (!st.empty())
st.pop();
else
ret++; // 缺少左
}
}
// 剩余左
while (!st.empty()) {
st.pop();
ret += 2;
}
return ret;
}
};
lc1590
同余优化
前缀和+hash
类似于两数之和的hash做法,枚举右维护左
只要是要看到同余就想到特性~
typedef long long ll;
class Solution {
public:
int minSubarray(vector<int>& nums, int p) {
int n = nums.size();
ll total = 0;
for (int num : nums) total += num;
ll mod = total % p;
if (mod == 0) return 0;
vector<ll> ps(n + 1, 0);
for (int i = 1; i <= n; i++) {
ps[i] = ps[i - 1] + nums[i - 1];
}
unordered_map<ll, int> mp;
mp[0] = 0;
int ret = INT_MAX;
for (int i = 1; i <= n; i++) {
ll currMod = ps[i] % p;
ll targetMod = (currMod - mod + p) % p;
if (mp.count(targetMod)) {
ret = min(ret, i - mp[targetMod]);
}
mp[currMod] = i;
}
return ret == n ? -1 : ret;
}
};
lc3152
前缀和 简化为单边的顺序考虑
(把某一个条件 抽象为 前缀判断也行got it
ans[i] = s[q[0]] == s[q[1]];

class Solution {
public:
vector<bool> isArraySpecial(vector<int>& nums, vector<vector<int>>& queries) {
vector<int> s(nums.size());
for (int i = 1; i < nums.size(); i++) {
s[i] = s[i - 1] + (nums[i - 1] % 2 == nums[i] % 2);
}
vector<bool> ans(queries.size());
for (int i = 0; i < queries.size(); i++) {
auto& q = queries[i];
ans[i] = s[q[0]] == s[q[1]];
}
return ans;
}
};
