记录详情 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)(单调栈优化DP--重点学习)
#include<iostream>
#include<stack>
using namespace std;
const int N=500005;
long long a[N];
long long s[N];
long long dpl[N],dpr[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int top=0;
for(int i=1;i<=n;i++){
while(top&&a[s[top]]>a[i])top--;
int now=s[top];
dpl[i]=a[i]*(i-now)+dpl[now];
s[++top]=i;
}
while(top)top--;
s[++top]=n+1;
for(int i=n;i>0;i--){
while(top&&a[s[top]]>a[i])top--;
int now=s[top];
dpr[i]=a[i]*(now-i)+dpr[now];
s[++top]=i;
}
long long ans=0;
int p=0;
for(int i=1;i<=n;i++){
if(dpr[i]+dpl[i]-a[i]>ans){
ans=dpr[i]+dpl[i]-a[i];
p=i;
}
}
int cnt=a[p];
for(int i=p;i>0;i--){
if(a[i]>=cnt){
a[i]=cnt;
}
else {
cnt=a[i];
}
}
cnt=a[p];
for(int i=p;i<=n;i++){
if(a[i]>=cnt){
a[i]=cnt;
}
else {
cnt=a[i];
}
}
for(int i=1;i<=n;i++){
cout<<a[i]<<' ';
}
}
P1823 [COI2007] Patrik 音乐会的等待 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) (单调栈--两元素间所有元素均(不)大/小于这两者)
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
#define ll long long
const int N=500005;
long long a[N];
inline ll read(){
ll d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int main(){
int n=read();
ll ans=0;
stack<pair<int,int> >q;
for(int i=0;i<n;i++){
int x=read();
int cnt=0;
while(!q.empty()&&q.top().first<=x){
if(q.top().first==x)
cnt=q.top().second;
ans+=q.top().second;
q.pop();
}
if(!q.empty())ans++;
q.emplace(x,cnt+1);
}
cout<<ans<<endl;
}
918. 环形子数组的最大和 - 力扣(LeetCode) (dp+最大前缀--重点学习)
class Solution {
public:
int maxSubarraySumCircular(vector<int>& nums) {
int n = nums.size();
vector<int> leftMax(n);
leftMax[0] = nums[0];
int leftSum = nums[0];
int pre = nums[0];
int res = nums[0];
for (int i = 1; i < n; i++) {
pre = max(pre + nums[i], nums[i]);
res = max(res, pre);
leftSum += nums[i];
leftMax[i] = max(leftMax[i - 1], leftSum);
}
int rightSum = 0;
for (int i = n - 1; i > 0; i--) {
rightSum += nums[i];
res = max(res, rightSum + leftMax[i - 1]);
}
return res;
}
};
Discrete Centrifugal Jumps - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)(和上上题类似)
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
#define ll long long
const int N=500005;
long long a[N];
int dp[N];
inline ll read(){
ll d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int main(){
int n=read();
stack<int>q1;
stack<int>q2;
for(int i=0;i<n;i++){
a[i]=read();
dp[i]=1e9+6;
}
dp[0]=0;
for(int i=0;i<n;i++){
while(!q1.empty()&&a[q1.top()]>a[i]){
dp[i]=min(dp[q1.top()]+1,dp[i]);
q1.pop();
}
if(!q1.empty()){
dp[i]=min(dp[q1.top()]+1,dp[i]);
}
if(!q1.empty()&&a[q1.top()]==a[i]){
q1.top()=i;
}
else q1.push(i);
while(!q2.empty()&&a[q2.top()]<a[i]){
dp[i]=min(dp[q2.top()]+1,dp[i]);
q2.pop();
}
if(!q2.empty()){
dp[i]=min(dp[q2.top()]+1,dp[i]);
}
if(!q2.empty()&&a[q2.top()]==a[i]){
q2.top()=i;
}
else q2.push(i);
}
cout<<dp[n-1]<<endl;
}