代码源 Div1#103子串的最大差 Codeforces - 817D,力扣2104,1900分
Posted 小哈里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码源 Div1#103子串的最大差 Codeforces - 817D,力扣2104,1900分相关的知识,希望对你有一定的参考价值。
problem
视频讲解链接:https://www.bilibili.com/video/BV1Du411X7Nk
solution
-
可以直接推导原答案ans = ∑ i = 1 n ∑ j = i n ( m a x − m i n ) = ∑ i = 1 n ∑ j = i n m a x − ∑ i = 1 n ∑ j = i n m i n \\sum_i=1^n\\sum_j=i^n(max-min) = \\sum_i=1^n\\sum_j=i^nmax-\\sum_i=1^n\\sum_j=i^nmin ∑i=1n∑j=in(max−min)=∑i=1n∑j=inmax−∑i=1n∑j=inmin,即对于每一段来说的最大值和最小值。
-
或者从贡献的角度考虑:对于一个数Ai来讲,如果其有贡献的价值,要么是-Ai作为最小值,要么是+Ai作为最大值。
那么Ans=ΣAi*maxn-Ai*minn,这里maxn表示Ai作为最大值出现的次数,minn表示Ai作为最小值出现的次数。 -
考虑如何计算这个maxn和minn
我们设定L【i】表示Ai作为最大值时,左边可以延展到的位子,R【i】表示Ai作为最大值时,右边可以延展到的位子。
那么对于Ai来讲,其maxn=(i-L【i】+1)-(R【i】-i+1);
L【i】以及R【i】都可以O(n)维护。
那么求minn的过程同理相反。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e6+10;
LL a[maxn], l[maxn], r[maxn];
int main()
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n; cin>>n;
for(int i = 1; i <= n; i++)cin>>a[i];
LL ans = 0;
//maxn
for(LL i = 1; i <= n; i++)l[i]=r[i]=i;
for(int i = 2; i <= n; i++)
int now = i;
while(now>1&&a[i]>=a[now-1])now=l[now-1];
l[i] = now;
for(int i = n-1; i >= 1; i--)
int now = i;
while(now<n&&a[i]>a[now+1])now=r[now+1];
r[i] = now;
for(LL i = 1; i <= n; i++)
ans += a[i]*(i-l[i]+1)*(r[i]-i+1);
//minn
for(LL i = 1; i <= n; i++)l[i]=r[i]=i;
for(int i = 2; i <= n; i++)
int now = i;
while(now>1&&a[i]<=a[now-1])now=l[now-1];
l[i] = now;
for(int i = n-1; i >= 1; i--)
int now = i;
while(now<n&&a[i]<a[now+1])now=r[now+1];
r[i] = now;
for(LL i = 1; i <= n; i++)
ans -= a[i]*(i-l[i]+1)*(r[i]-i+1);
cout<<ans<<"\\n";
return 0;
以上是关于代码源 Div1#103子串的最大差 Codeforces - 817D,力扣2104,1900分的主要内容,如果未能解决你的问题,请参考以下文章