题解 P6503 【[COCI2010-2011#3] DIFERENCIJA】
题面传送门。
题意简述:给出
n 和a_i ,求\sum_{i=1}^n\sum_{j=i}^n\left(\max_{i\leq k\leq j}a_k-\min_{i\leq k\leq j}a_k\right)
提供一个不一样的思路。
我们设
考虑如何维护
不妨设
稍微解释一下上面的转移方程是如何得来的:
- 因为
a_i 对p_i 以及p_i 以前的最大值没有影响(即[1,p_i] 与[1,i] ,[2,p_i] 与[2,i]\cdots [p_i,p_i] 与[p_i,i] 的最大值相同),所以可以直接由f_{p_i} 转移得来。 - 而根据
p_i 的定义,后面i-p_i 个子序列(即[p_i+1,i],[p_i+2,i]\cdots,[i,i] )的最大值为a_i ,所以加上a_i\times (i-p_i) 。 - 所以转移方程为
f_i=f_{p_i}+a_i\times (i-p_i) 。
维护
时间复杂度
const int N=3e5+5;
ll n,t1,t2,ans,f[N],g[N];
pii a[N],b[N];
int main(){
n=read();
for(int i=1;i<=n;i++){
ll x=read(),p;
while(t1&&x>=a[t1].fi)t1--;
while(t2&&x<=b[t2].fi)t2--;
p=a[t1].se; f[i]=f[p]+x*(i-p);
p=b[t2].se; g[i]=g[p]+x*(i-p);
ans+=f[i]-g[i],a[++t1]=b[++t2]={x,i};
} cout<<ans<<endl;
return 0;
}