吃蛋糕 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;
}

你可能感兴趣的:(吃蛋糕 cate题解)