牛客——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 }

 

posted @ 2019-07-19 16:41  Chuhanjing  阅读(244)  评论(0编辑  收藏  举报