做题记录整理枚举4 P817D. Imbalanced Array(2022/9/9)
这题的启示是要学好英语
cf那里没有中文,所以就直接用洛谷的了
这题的第一个难点是需要想到从计算区间贡献变为计算点的贡献
每个点对答案的贡献就是:数的值*(它作为最大值的区间个数-它作为最小值的区间个数)
(这个可以说是最阴间的地方,能想到这个的人后面的单调栈肯定也是能想到的)
所以我们可以自然的想到他作为最大值的区间个数取决于他的左边和右边第一个比他大的数(比他大还取的话他当然就不是最大值了),最小值同理
因此问题就转化成了求一个数左/右边第一个比他大/小的数了,可以自然的想到使用单调栈
启示:在区间计数问题中可以多去思考点对答案的贡献
#include<bits/stdc++.h>
#define for1(i,a,b) for(int i = a;i<=b;i++)
#define ll long long
#define mp(a,b) make_pair(a,b)
using namespace std;
int n,a[5000005],zhan[5000005],top;
ll ans;
int l[500005],r[500005];
int l2[50005],r2[500005];
int main()
{
cin>>n;
for1(i,1,n)
scanf("%d",a+i);
for1(i,1,n)
{
while(top!=0&&a[zhan[top]]<a[i]) top--;
if(top!=0)
l[i]=zhan[top];
zhan[++top]=i;
}
top=0;
for(int i=n;i>=1;i--)
{
while(top!=0&&a[zhan[top]]<=a[i]) top--;
if(top!=0)
r[i]=zhan[top];
else r[i]=n+1;
zhan[++top]=i;
}
top=0;
for1(i,1,n)
{
while(top!=0&&a[zhan[top]]>a[i]) top--;
if(top!=0)
l2[i]=zhan[top];
zhan[++top]=i;
}
top=0;
for(int i=n;i>=1;i--)
{
while(top!=0&&a[zhan[top]]>=a[i]) top--;
if(top!=0)
r2[i]=zhan[top];
else r2[i]=n+1;
zhan[++top]=i;
}
for1(i,1,n)
ans+=1ll*a[i]*(1ll*(i-l[i])*(r[i]-i)-1ll*(i-l2[i])*(r2[i]-i));
cout<<ans;
return 0;
}

浙公网安备 33010602011771号