牛客——Neat Tree(单调栈)
维护一个单调增、一个单调减链,计算每个元素最为最大值或最小值被计算的次数。
num[i]记录对于元素a[i]最为最大值或者最小值往左能走的最远距离,这道题其实和poj那个算矩形的差不多,每次元素出栈的时候就能计算出该元素的右边界。
然后就有计算这个元素的贡献:ans-=(num1[S1.top()]*(i-S1.top())*a[S1.top()])
对于相等的元素出不出栈都行
坑点在于数据非常大,要long long
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e6+5; 4 const int INF=99999999; 5 typedef long long ll; 6 int a[maxn]; 7 int b[maxn]; 8 int num1[maxn]; 9 int num2[maxn]; 10 int main(){ 11 int n; 12 /*freopen("in.txt","r",stdin); 13 freopen("b1.txt","w",stdout);*/ 14 while(cin>>n){ 15 for(int i=1;i<=n;i++) 16 { 17 scanf("%d",&a[i]); 18 b[i]=a[i]; 19 } 20 memset(num1,0,sizeof(num1)); 21 memset(num2,0,sizeof(num2)); 22 a[n+1]=0;b[n+1]=INF; 23 stack <int> S1,S2; 24 S1.push(1);num1[1]=1;S2.push(1);num2[1]=1; 25 ll ans=0; 26 for(int i=2;i<=n+1;i++){ 27 long long tmp=1; 28 while(!S1.empty()&&a[i]<=a[S1.top()]) 29 { 30 tmp+=num1[S1.top()]; 31 ans-=(num1[S1.top()]*(i-S1.top())*a[S1.top()]); 32 //cout <<ans<<endl; 33 S1.pop(); 34 } 35 num1[i]=tmp; 36 S1.push(i); 37 tmp=1; 38 while(!S2.empty()&&b[i]>=b[S2.top()]) 39 { 40 tmp+=num2[S2.top()]; 41 ans+=(num2[S2.top()]*(i-S2.top())*b[S2.top()]); 42 S2.pop(); 43 } 44 num2[i]=tmp; 45 S2.push(i); 46 } 47 cout <<ans<<endl; 48 } 49 return 0; 50 }