【题解】P6503 DIFERENCIJA
题面
前言
绿题,爆切我
世界,遗忘我
正文
这是一个经典操作:找到一个值为为最大值的最大区间长度/区间个数
那么在单调栈里这个数的前一个数就是他的左边界限,反过来做一下就能确定右端点
最小值一样
直接贴一个很清晰的题解代码
代码
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<stack>
#define int long long
const int MN=3e5+5;
using namespace std;
int a[MN];
int Lmax[MN],Rmax[MN],Lmin[MN],Rmin[MN];
stack<int>s;
int n;
signed main(void){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
while(!s.empty()&&a[s.top()]<=a[i])s.pop();
if(s.empty())Lmax[i]=0;
else Lmax[i]=s.top();
s.push(i);
}
while(!s.empty())s.pop();
for(int i=1;i<=n;i++){
while(!s.empty()&&a[s.top()]>=a[i])s.pop();
if(s.empty())Lmin[i]=0;
else Lmin[i]=s.top();
s.push(i);
}
while(!s.empty())s.pop();
for(int i=n;i>=1;i--){
while(!s.empty()&&a[s.top()]<a[i])s.pop();
if(s.empty())Rmax[i]=n+1;
else Rmax[i]=s.top();
s.push(i);
}
while(!s.empty())s.pop();
for(int i=n;i>=1;i--){
while(!s.empty()&&a[s.top()]>a[i])s.pop();
if(s.empty())Rmin[i]=n+1;
else Rmin[i]=s.top();
s.push(i);
}
int ans=0;
for(int i=1;i<=n;i++){
ans=ans+a[i]*(i-Lmax[i])*(Rmax[i]-i);
ans=ans-a[i]*(i-Lmin[i])*(Rmin[i]-i);
}
cout<<ans<<endl;
return 0;
}
后记
不 ~ 开 ~ 心 ~
完结撒花!