P1823 [COI2007] Patrik 音樂會的等待

10 篇文章 0 订阅
4 篇文章 0 订阅

題目連結:[COI2007] Patrik 音乐会的等待 - 洛谷

一開始看到題目有種逆序對的感覺,但題目說明中間若有比自己高的點就不算一對,這就不關逆序對的事情了。

1. 中間不能有比自己高的人

2. 相鄰兩個人可以算一對

從這個特性我們知道,假設前面有k個人,他們的升高都是降序排好的,如果有一個人進來了,他比這k個人都大,那麼如果第k + 2個人進來,我們可以保證這k + 2個人都不能和這k個人湊成一對,因為第k+1個人比前k個人要高,這就是題目給的條件1。

那這就挺適合用單調棧的了,我們保證單調棧是降序的,一旦有比棧頂高的人進來,那就說明棧內所有比這個人矮的人都能成一對,因為我們的棧是降序的。

那麼考慮一下一樣高的人進來怎麼辦?他不能只對答案貢獻1啊,因為棧內的其他人也有可能和他湊成一對,一會進來的人也能跟他湊成一對,那可以怎麼辦?

想到這裡我就可以用一個結構體,把重複的身高記一下,一會有比當前高的人進來,我們就不用擔心我們把前面的人彈出棧導致正確性不能保證了,並且整個棧都是保證絕對降序,不會有一樣的存在,而且對答案的貢獻是出現的次數。

代碼 很簡單就是普通的棧,加上結構體。

#include <iostream>
#include <vector>
using namespace std;
int n;
long long ans = 0;
struct node{
    int val, num;
};
vector<node> s;
int main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        int a;
        cin >> a;
        node m = (node){a, 1};
        while(!s.empty() && s.back().val <= a){
            ans += s.back().num;
            if(s.back().val == a){
                m.num +=s.back().num;
            }
            s.pop_back();
        }
        //reason 1
        if(!s.empty())ans++;
        s.push_back(m);
    }
    cout << ans << endl;
    return 0;
}

reason 1

如果棧一直被彈出,並且是空的,那麼答案無需匹配,因為最後沒有人可以跟新進來的人進行匹配,但是如果棧不是空,也就是說最後有人可以和新進來的人進行匹配,答案就要加1,不然會少算一對。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值