2020 GDUT Rating Contest I (Div. 2) D - Meetings 题解

原题在这里插入图片描述

题目大意

有n只牛运货,要运到0粮仓和l粮仓里,如果两头牛碰面,那么它们各自回头走,运完一半就停止

题目分析

这题在比赛的时候没有做出来……主要是因为不知道怎么帮牛找回自己的包袱。
很明显的是,两头牛相碰的时候可以当作穿过去,他们的重量交换,这个数据规模不能直接跑模拟,所以要二分找结束时间,结束时间也不难找,主要还是怎么帮牛牛找回自己的包袱。
后来发现,不管牛牛怎么相碰,运到的重量还是按照其坐标离终点先后来运达的,所以我对它们进行了一次按x升序排序,然后二分检查两边各到了多少头牛,再把包袱分配下去就行了。
最后就是找出有多少次相遇,只需将走完后的序列和走前的序列对比,对每只向左走的牛跨越了多少只牛就是答案了(重叠也是个问题……我看了一下别人的,最方便的好像就是各加0.1了)

代码

#include<cstdio>
#include<cstdlib>
#include<algorithm>
typedef struct cow
{
    int num;
    int w;
    double x;
    int d;
};
 
cow all[50011];
int index[50011];
int pt = 0,nt = 0,reach = 0,sumw = 0,endt;
int n,L;
bool cmpx(cow a,cow b)
{
    return a.x < b.x;
}
bool check(int x)
{
    int lb = 0,rb = 0;
    for (int i = 0;i < n;++i)
    {
        int t = all[i].x + all[i].d * x;
        if (t <= 0) ++lb;
        if (t >= L) ++rb;
    }
    int tot = 0;
    for (int i = 0;i < lb;++i) tot += all[i].w;
    for (int i = 0;i < rb;++i) tot += all[n - i - 1].w;
    if (tot * 2 >= sumw) return true;
    else return false;
}
int main()
{
    int ans = 0;
    scanf("%d%d",&n,&L);
    for (int i = 0;i < n;i++)
    {
        int w,x,d;
        scanf("%d%d%d",&w,&x,&d);
        sumw += w;
        all[i].w = w,all[i].x = x,all[i].num = i,all[i].d = d;
    }
    std::sort(all,all + n,cmpx);
    for (int i = 0;i < n;++i) index[all[i].num] = i;
    int l = 0,r = L;
    while (l <= r)
    {
        int mid = (l + r) >> 1;
        if (check(mid)) r = mid - 1;else l = mid + 1;        
    }
    for (int i = 0;i < n;++i)
        if (all[i].d == 1) all[i].x += l + 0.1;else all[i].x -= l + 0.1;
    std::sort(all,all + n,cmpx);
    for (int i = 0;i < n;++i)
        if (all[i].d == 1) ans += abs(index[all[i].num] - i);
    printf("%d",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值