【Codeforces257E】Greedy Elevator

3 篇文章 0 订阅
1 篇文章 0 订阅

题意:
有一个电梯,有 n 个人。
i个人会在 ti 时刻来到 si 层的电梯口,并想要去 ti 层。
每一个时刻,设 pup 为想要去楼上的在电梯中的人数与在楼上等待的人数之和, pdown 为想要去楼下的在电梯中的人数与在楼下等待的人数之和,若 puppdown 则向上走一层,否则向下走一层。输出每个人到达目的地的时刻。

4个set维护四种人,关键时刻只有 O(n) 个,所以暴力模拟就好了。
时间复杂度 O(nlogn)

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define N 100009
#define inf 0x3f3f3f3f
using namespace std;
int n,m;
ll Ans[N];
int read()
{
    int x=1;
    char ch;
    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
    int s=ch-'0';
    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';
    return x*s;
}
struct passenger
{
    int t,s,f,pos;
    void scan(int i)
    {
        t=read(),s=read(),f=read(),pos=i;
    }
    bool operator <(const passenger &rhs) const
    {
        return t<rhs.t;
    }
}p[N],q[N];
struct node
{
    int id,pos;
    node(int id=0,int pos=0):id(id),pos(pos){}
    bool operator <(const node &rhs) const
    {
        return pos<rhs.pos;
    }
    bool operator >(const node &rhs) const
    {
        return pos>rhs.pos;
    }
};
multiset<node,less<node> > to_up,from_up;
multiset<node,greater<node> > to_down,from_down;
int pos=1,finish=0,id=1;
ll t=1;
void add_from()
{
    while (p[id].t==t)
    {
        if (pos==p[id].s)
        {
            if (p[id].f>pos) to_up.insert(node(p[id].pos,p[id].f));
            else to_down.insert(node(p[id].pos,p[id].f));
        }
        else
        {
            if (p[id].s>pos) from_up.insert(node(p[id].pos,p[id].s));
            else from_down.insert(node(p[id].pos,p[id].s));
        }
        id++;
    }
}
int main()
{
    n=read(),m=read();
    for (int i=1;i<=n;i++)
        p[i].scan(i),q[i]=p[i];
    sort(p+1,p+n+1);
    to_up.insert(node(0,inf)),from_up.insert(node(0,inf));
    to_down.insert(node(0,-inf)),from_down.insert(node(0,-inf));
    while (finish<n)
    {
        int size1=to_up.size()+from_up.size();
        int size2=to_down.size()+from_down.size();
        //puts("ok");
        if (size1==2&&size2==2)
        {
            if (id>n) break;
            t=p[id].t,add_from();
            continue;
        }
        if (size1>=size2)
        {
            node now1=*(to_up.begin());
            node now2=*(from_up.begin());
            if (id<=n&&p[id].t-t<now1.pos-pos&&p[id].t-t<now2.pos-pos)
            {
                pos+=p[id].t-t;
                t=p[id].t,add_from();
            }
            else
            {
                if (now1>now2) swap(now1,now2);
                t+=(ll)now1.pos-pos;
                pos=now1.pos;
                node now;
                while ((now=*(to_up.begin())).pos==pos)
                {
                    Ans[now.id]=t;
                    to_up.erase(to_up.find(now));
                    finish++;
                }
                while ((now=*(from_up.begin())).pos==pos)
                {
                    from_up.erase(from_up.find(now));
                    if (q[now.id].f>pos) to_up.insert(node(now.id,q[now.id].f));
                    else to_down.insert(node(now.id,q[now.id].f));
                }
                add_from();
            }
        }
        else
        {
            node now1=*(to_down.begin());
            node now2=*(from_down.begin());
            if (id<=n&&p[id].t-t<pos-now1.pos&&p[id].t-t<pos-now2.pos)
            {
                pos-=p[id].t-t;
                t=p[id].t,add_from();
            }
            else
            {
                if (now1<now2) swap(now1,now2);
                t+=(ll)pos-now1.pos;
                pos=now1.pos;
                node now;
                while ((now=*(to_down.begin())).pos==pos)
                {
                    Ans[now.id]=t;
                    to_down.erase(to_down.find(now));
                    finish++;
                }
                while ((now=*(from_down.begin())).pos==pos)
                {
                    from_down.erase(from_down.find(now));
                    if (q[now.id].f>pos) to_up.insert(node(now.id,q[now.id].f));
                    else to_down.insert(node(now.id,q[now.id].f));
                }
                add_from();
            }
        }
        //cout<<t<<" "<<pos<<endl;
    }
    for (int i=1;i<=n;i++)
        printf("%lld\n",Ans[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值