/* 单调栈 *///最小值是在一段连续数字钟被筛选出来的,也就是说每个最小值都有一定intsumSubarrayMins(vector<int>&arr){int n = arr.size();
vector<int>left(n),right(n);//每个元素辐射范围的左右边界
stack<int> st;for(int i =0; i < n; i++){//向左寻找第一个小于等于 E 的元素 (小于“等于”为了解决重复相同最小值元素)while(!st.empty()&& arr[i]< arr[st.top()])
st.pop();if(st.empty())
left[i]=-1;else
left[i]= st.top();
st.push(i);}
st =stack<int>();for(int i = n -1; i >=0; i--){//向右寻找第一个小于 E 的元素while(!st.empty()&& arr[i]<= arr[st.top()])
st.pop();if(st.empty())
right[i]= n;else
right[i]= st.top();
st.push(i);}//计算贡献值//左右边界实际上记录的是 左边界-1 和 右边界+1long ans =0;for(int i =0; i < n; i++)
ans =(ans +(long)(i - left[i])*(right[i]- i)* arr[i])%1000000007;return(int)ans;}//Time O(n) Space O(n)
/* 平衡法 *///计算每个前缀数组的平衡度,负值代表需要加 '(',正值代表需要加 ')'intminAddToMakeValid(string s){int ans =0, bal =0;for(int i =0; i < s.size(); i++){
bal += s.[i]=='('?:1:-1;if(bal ==-1){
ans++;
bal++;//保持 bal >= -1}}return ans + bal;}
intclumsy(int n){
stack<int> st;
st.push(n);
n--;int index =0;while(n >0){//栈中存计算结果if(index %4==0)
st.top()*= n;elseif(index %4==1)
st.top()/= n;elseif(index %4==2)
st.push(n);
eles
st.push(-n);
index++;
n--;}int sum =0;while(!st.empty()){
sum += st.top();
st.pop();}return sum;}//Time O(n) Space O(n)
/* 数学 */intclumsy(int n){if(n ==1)return1;elseif(n ==2)return2;elseif(n ==3)return6;elseif(n ==4)return7;if(n %4==0){return n +1;elseif(n %4<=2)return n +2;elsereturn n -1;}//Time O(1) Space O(1)
/* 枚举 *///枚举矩阵每个位置 (i, j) 作为右下角时有多少符合要求的子矩阵//row 代表矩阵中 (i, j) 向左延伸连续的 1 的个数。有 row 数组后,枚举子矩阵高 k intbumSubmat(vector<vector<int>>&mat){int n = mat.size(), m = mat[0].size();
vector<vector<int>>row(n,vector<int>(m,0));for(int i =0; i < n; i++){for(int j =0; j < m; j++){if(j ==0){
row[i][j]= mat[i][j];}elseif(mat[i][j]){
row[i][j]= row[i][j -1]+1;}else{
row[i][j]=0;}}}int ans =0;for(int i =0; i < n; i++){for(int j =0; j < m; j++){int col = row[i][j];for(int k = i; k >=0&& col; k--){
col =min(col, row[k][j]);
ans += col;}}}return ans;}//Time O(n^2 * m) Space O(nm)
/* 单调栈 */intbumSubmat(vector<vector<int>>&mat){int n = mat.size(), m = mat[0].size();
vector<vector<int>>row(n,vector<int>(m,0));for(int i =0; i < n; i++){for(int j =0; j < m; j++){if(j ==0){
row[i][j]= mat[i][j];}elseif(mat[i][j]){
row[i][j]= row[i][j -1]+1;}else{
row[i][j]=0;}}}int ans =0;for(int j =0; j < m;++j){//纵向由列开始统计
stack<pair<int,int>> monost;// < row[i][j], height >int sum =0;for(int i =0; i < n; i++){int height =1;while(!monost.empty()&& monost.top().first > row[i][j]){
sum -= monost.top().second *(monost.top().first - row[i][j]);//弹出时减去多于答案
height += monost.top().second;
monost.pop();}
sum += row[i][j];
ans += sum;
monost.push({row[i][j], height});}}return ans;}//Time O(mn) Space O(?)
intminInsertion(string s){int ans =0;int left =0;int n = s.size();int index =0;while(index < n){char c = s[index];if(c =='('){//char '('
left++;
index++;}else{//char ')'if(left >0){
left--;}else{
ans++;}if(index < n -1&& s[index +1]==')'){
index +=2;//char '))'}else{
ans++;
index++;}}}
ans += left *2;return ans;}
/* 贪心 *///优先处理得分高的字符串,然后处理栈中剩余的低分子串intmaximumGain(string s,int x,int y){//ab 得 x 分, ba 得 y 分
stack<char> ba, ab;int ret =0;if(x > y){//预处理,统一默认 ba 得 y 为高分swap(x, y);reverse(s.begin(), s.end());}for(char c : s){//ba 高分if(c !='a'){//栈中弹出顺序实际为 ba 故先判断 a
ba.push(c);}else{//新扫描到的字符为 a if(!ba.empty()&& ba.top()=='b'){
ba.pop();//组成 ba
ret += y;}else{
ba.push(c);}}}while(!ba.empty()){//处理 abchar c = ba.top();if(c !='a'){
ab.push(c);}else{if(!ab.empty()&& ab.top()=='b'){
ab.pop();
ret += x;}else{
ab.push(c);}}
ba.pop();}return ret;}
/* 单调栈 *///类似 84. 柱状图最大矩形面积intmaximumScore(vector<int>& nums,int k){int n = nums.size();
vector<int>left(n),right(n);//当前数字左侧最近的第一个比该数字较小元素
stack<int> st;for(int i =0; i < n; i++){while(!st.empty()&& nums[st.top()]>= nums[i])
st.pop();
left[i]= st.empty()?-1: st.top();
st.push(i);}//当前数字右侧最近的第一个比该数字较小元素
st =stack<int>();for(int i = n -1; i >=0; i--){while(!st.empty()&& nums[st.top()]>= nums[i])
st.pop();
right[i]= st.empty()? n : st.top();
st.push(i);}int ans =0;for(int i =0; i < n; i++){if(left[i]< k && right[i]> k)
ans =max(ans,(right[i]- left[i]-1)* nums[i]);}return ans;}