喫蛋糕 cate題解

題目描述

小明是個蛋糕愛好者,連做夢都想着喫蛋糕——然後,他真的作了這樣一個夢:
現在他在一個長爲L的管道里,座標從0~L,開始時,他在0這個位置。
一些事件依次發生,比如說,小明想喫蛋糕,或者是蛋糕出現了。
如果小明想喫蛋糕,那麼他會挑選最近的那個蛋糕喫掉。如果左右兩個蛋糕的距離是一樣的,那麼他就選擇跟喫上一個蛋糕同樣移動方向上的。否則,他就選那個距離較近的蛋糕。要是一個蛋糕都沒出現,那麼他就呆在原地不動。
蛋糕會隨機出現在管道的任何位置。
請你統計一下,小明一共走了多少距離。

輸入

輸入第一行是兩個整數L,N。L是管道的長度,N是事件的數量。(1<=L,N<=100000)
接下來N行,首先是一個整數,表示事件的種類:如果是1,表示小明要喫蛋糕,後面什麼也沒有;如果是0,表示有個蛋糕出現了,後面跟一個整數,表示蛋糕出現的位置。(0<=x<=L)

輸出

輸出一個整數,表示小明一共走了多少距離。

樣例輸入

10 8
0 1
0 5
1
0 2
0 0
1
1
1

樣例輸出

9

提示

【樣例輸入2】

10 7

0 1

0 5

1

0 2

0 0

1

1

【樣例輸出2】

4

【數據描述】

對於50%的數據,L,N<=5000

對於100%的數據,L,N<=100000

想法

  • 用兩個堆來維護左邊與右邊

算法

  • 見代碼

代碼

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
using namespace std;
priority_queue<int> l;
priority_queue<int,vector<int>,greater<int> > r;
int L,N,now,opt,pos,ans,cnt;
bool dir=1;
inline void work(int x)
{
    int temp;
    if(x)
    {
        temp=r.top();r.pop();
        ans+=temp-now;
        now=temp;dir=1;
    }
    else
    {
        temp=l.top();l.pop();
        ans+=now-temp;
        now=temp;dir=0;
    }
}
int main()
{
    scanf("%d%d",&L,&N);
    for (int i=1;i<=N;i++)
    {
        scanf("%d",&opt);
        if(!opt)
        {
            scanf("%d",&pos);
            if(pos==now)cnt++;
            else pos>now?r.push(pos):l.push(pos);
        }
        else
        {
            if(cnt>0){cnt--;continue;}
            else if(l.empty()||r.empty())
            {
                if(l.empty()&&r.empty())continue;
                else if(l.empty())work(1);
                else if(r.empty())work(0);
            }
            else
            {
                int ll=l.top(),rr=r.top();
                if(now-ll==rr-now){work(dir);continue;}
                else
                    now-ll>rr-now?work(1):work(0);
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章