P1823 [COI2007] Patrik 音乐会的等待 洛谷

原题链接

很容易分析出边界点是身高比h[i]高的人,单调栈里是形成单调递减栈.能与h[i]形成一对的人h<=h[i],而且h[i]能看到离他最近的比他高的人,所以本题我们需要利用单调栈的边界点和while循环里pop的点,因为要避免重复,所以我们只需要从左边或右边开始计算对数,而且我们还需要统计身高相同的人,因为身高相同的人也会被pop掉。

切入点是top与h[i]的值,如果top>h[i]那么普通地+1即可,如果top<=h[i],我们需要不断pop直到达到左边条件.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 typedef pair<int,int> pii;
 5 const int N = 5e5+10;
 6 ll ans;
 7 int h;
 8 pii p[N];//思路,被pop掉的人都比h[i]矮,因此可以交流, 此前的情况:a,b,c(a.h<b.h<c.h) c可看a但a不可看c,实际在c计算之前b就会把a pop掉
 9 //栈内是一个单调递减的序列(h[i]一定可以与栈内比他矮之人交流,h[i]与栈形成的曲线是类似x^2的曲线)
10 //要注意身高相同的情况 ,他会被与他身高相同的人pop掉
11 int main()
12 {
13     stack<pii> stk;
14     int n; scanf("%d",&n);
15     for(int i=1;i<=n;i++){
16         scanf("%d",&h);
17         p[i] = {h,1};
18         for(;!stk.empty()&&stk.top().first<=h;stk.pop()){
19             ans+=stk.top().second;
20             if(stk.top().first==h) p[i].second+=stk.top().second;//之前身高相等的人数
21         }
22         if(!stk.empty()) ans++;//还能与比他高的 最近的交流
23         stk.push(p[i]);
24     }
25     printf("%lld\n",ans);
26     return 0;
27 }

 

posted @ 2020-12-29 13:58  acmloser  阅读(68)  评论(0编辑  收藏  举报