1. 程式人生 > >NowCoder--牛可樂發紅包脫單ACM賽C_區區區間間間

NowCoder--牛可樂發紅包脫單ACM賽C_區區區間間間

題目連結: C_區區區間間間

思路:算貢獻,求出每個數為當前最大值時所在的區間個數,和每個數為最小值的區間個數 

和這個題有點類似 搭配食用效果更佳  點選這裡

#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
#define LL long long
LL ll[maxn],rr[maxn],a[maxn];
LL work(LL n){
    memset(ll,0,sizeof(ll));
    memset(rr,0,sizeof(rr));
   stack
<int>s,t; for(LL j=1;j<=n;j++){ while(s.size()&&a[j]>=a[s.top()]){ s.pop(); } if(!s.size()) ll[j]=1; else ll[j]=s.top()+1; s.push(j); } for(LL j=n;j>=1;j--){ while(t.size()&&a[j]>a[t.top()]){ t.pop(); }
if(!t.size()) rr[j]=n; else rr[j]=t.top()-1; t.push(j); } LL ans=0; for(LL j=1;j<=n;j++){ ans+=1LL*a[j]*1LL*(rr[j]-ll[j]+(rr[j]-j)*(j-ll[j])); } return ans; } int main(){ LL t; cin>>t; while(t--){ LL n; cin>>n;
for(LL j=1;j<=n;j++){ scanf("%d",&a[j]); } LL ans=work(n); //cout<<ans<<endl; for(LL j=1;j<=n;j++){ // 賦值的時候相當於找最大 得到的結果就是負數 正好減去 a[j]=-a[j]; } ans+=work(n); cout<<ans<<endl; } }