Imbalanced Array
题目
解析
学单调栈时偶然看到了这一题,就写掉了
想一下暴力,O(n3),n<=106,神威太湖之光都跑不过去
加个ST表,O(n2),天河二号跑得过去,你谷评测姬就别想了
考虑每个点对结果贡献,得到是左右拓展,最优是O(n),随便构造一个数据就退化为O(n2)了
加上单调栈优化,然后就做到了了传说中的O(n)!
稳稳过掉
附:居然放过去了一位O(nlogn)的,希望早日把n开到107
第一篇题解是同机房的dalao写的,但说错了一点:longlong不会炸,害的我去翻int128
code:
#include<cstdio>
#define int long long
#define rr register int
using namespace std;
inline bool idigit(char x){
return (x<'0'|x>'9')?0:1;}
inline int read()
{
int num=0,f=1;
char c=0;
while(!idigit(c=getchar())){
if(c=='-')f=-1;}
while(idigit(c))num=(num<<1)+(num<<3)+(c&15),c=getchar();
return num*f;
}
inline void write(int x)
{
int F[50];
int tmp=x>0?x:-x;
if(x<0)putchar('-');
int cnt=0;
while(tmp>0){
F[cnt++]=tmp%10+'0';tmp/=10;}
while(cnt>0)putchar(F[--cnt]);
if(x==0)putchar('0');
}
int n,st[1000010],tot,a[1000010],lmi[1000010],rmi[1000010],lmx[1000010],rmx[1000010],ans=0;
signed main()
{
n=read(),tot=1,st[1]=0;
for(rr i=1;i<=n;++i)a[i]=read();
for(rr i=1;i<=n;++i)
{
if(a[st[tot]]<a[i])lmi[i]=i-1,st[++tot]=i;
else
{
while(tot&&a[st[tot]]>a[i])--tot;
lmi[i]=st[tot],st[++tot]=i;
}
}//求最小左端点
tot=1,st[1]=n+1;
for(rr i=n;i;--i)
{
if(a[st[tot]]<a[i])rmi[i]=i+1,st[++tot]=i;
else
{
while(tot&&a[st[tot]]>=a[i])--tot;
rmi[i]=st[tot],st[++tot]=i;
}
}//求最小右端点
a[0]=a[n+1]=1e17,tot=1,st[1]=0;
for(rr i=1;i<=n;++i)
{
if(a[st[tot]]>a[i])lmx[i]=i-1,st[++tot]=i;
else
{
while(tot&&a[st[tot]]<a[i])--tot;
lmx[i]=st[tot],st[++tot]=i;
}
}//求最大左端点
tot=1,st[1]=n+1;
for(rr i=n;i;--i)
{
if(a[st[tot]]>a[i])rmx[i]=i+1,st[++tot]=i;
else
{
while(tot&&a[st[tot]]<=a[i])--tot;
rmx[i]=st[tot],st[++tot]=i;
}
}//求最大右端点
for(rr i=1;i<=n;++i)ans=ans+a[i]*((i-lmx[i])*(rmx[i]-i)-(i-lmi[i])*(rmi[i]-i));
write(ans);
return 0;
}