Richard神犇出给nowcoder的题
用单调栈找到每个点它向右和向左的第一个大于或小于它的位置,然后它作为最大值/最小值的区间就要在这个范围里,那么它的贡献就是这个区间长度乘一乘再减一减
注意一下值相等的时候怎么处理
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=1e6+10; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 int N,a[maxn]; 16 int stk[maxn][2],sh,mm[maxn]; 17 ll ans; 18 19 int main(){ 20 //freopen(".in","r",stdin); 21 int i,j,k; 22 while(~scanf("%d",&N)){ 23 for(i=1;i<=N;i++) a[i]=rd(); 24 CLR(mm,0);ans=0; 25 for(i=1;i<=N;i++){ 26 while(sh&&stk[sh][0]<a[i]){ 27 mm[stk[sh--][1]]=i-1; 28 } 29 stk[++sh][0]=a[i],stk[sh][1]=i; 30 }for(;sh;--sh) mm[stk[sh][1]]=N; 31 32 for(i=N;i;i--){ 33 while(sh&&stk[sh][0]<=a[i]){ 34 if(mm[stk[sh][1]]) ans+=1ll*(stk[sh][1]-i)*(mm[stk[sh][1]]-stk[sh][1]+1)*stk[sh][0]; 35 sh--; 36 } 37 stk[++sh][0]=a[i],stk[sh][1]=i; 38 }for(;sh;--sh) if(mm[stk[sh][1]]) ans+=1ll*stk[sh][1]*(mm[stk[sh][1]]-stk[sh][1]+1)*stk[sh][0]; 39 40 CLR(mm,0); 41 for(i=1;i<=N;i++){ 42 while(sh&&stk[sh][0]>a[i]){ 43 mm[stk[sh--][1]]=i-1; 44 } 45 stk[++sh][0]=a[i],stk[sh][1]=i; 46 }for(;sh;--sh) mm[stk[sh][1]]=N; 47 48 for(i=N;i;i--){ 49 while(sh&&stk[sh][0]>=a[i]){ 50 if(mm[stk[sh][1]]) ans-=1ll*(stk[sh][1]-i)*(mm[stk[sh][1]]-stk[sh][1]+1)*stk[sh][0]; 51 sh--; 52 } 53 stk[++sh][0]=a[i],stk[sh][1]=i; 54 }for(;sh;--sh) if(mm[stk[sh][1]]) ans-=1ll*stk[sh][1]*(mm[stk[sh][1]]-stk[sh][1]+1)*stk[sh][0]; 55 56 printf("%lld ",ans); 57 } 58 59 return 0; 60 }