D. Meetings

D. Meetings

https://codeforces.com/group/5yyKg9gx7m/contest/269717/problem/D

分析:

2头牛相遇看成交换2头牛的质量,方向不变。所以一头牛的终点可以是是固定的,那么离终点最近的就是最早进入仓的。所以他到达仓时的质量是他穿过的最后一头牛的质量。比如d为-1的x最小的牛,他的终点是0,也是最先到0的牛,所以他的质量是离0最近的方向与他相反的牛。以此类推,时间越短的牛与越接近终点的牛的质量配对。

依次取时间最小的,直到进仓质量为总的1/2,得到结束时间T。

算出一开始将要相遇的牛对数,和结束后,将要相遇的牛的对数,两个相减就是答案。

因为可能在T时刻,2头牛正好在同一处而又没有计算在相遇次数内。可以加减0.1让他们错位。因为至多有2头牛会在同一时刻停在同一位置。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
using namespace std;
typedef long long ll;
const int maxn=5e4+6;
struct cow
{
    int w;
    int x;
    int d;
    int t;
    double cx;//错位后的x 
}c[maxn],c2[maxn]//c2是存一开始按位置排,最接近仓的牛;
bool cmp1(struct cow a,struct cow b)
{
    return a.x<b.x;
}
bool cmp3(struct cow a,struct cow b)
{
    if(a.d==b.d) return a.x<b.x;
    return a.d<b.d;
}
bool cmp2(struct cow a,struct cow b)
{
    return a.cx<b.cx;
}
int n,L;
ll s;
int T=0;
void getT()
{
    //得到T 
    int mid=1;
    while(c[mid].d==-1) mid++;//有多少个向左走的 
    ll sum=0;
    int l=1,r=n;
    while(sum*2<s)
    {
        if((L-c[r].x>c[l].x&&l<mid)||r<mid)
        {
            sum+=c2[l].w;//这头牛的质量为相对接近终点的牛的质量 
            T=max(T,c[l].x);
            l++;        
        }
        else
        {
            sum+=c2[r].w;
            T=max(T,L-c[r].x);
            r--;
        }
    }
}
int main()
{
    cin>>n>>L;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&c[i].w,&c[i].x,&c[i].d);
        s+=c[i].w;
        if(c[i].d==1) c[i].t=L-c[i].x;
        else c[i].t=c[i].x;
    }
    sort(c+1,c+n+1,cmp1);
    memcpy(c2,c,sizeof c);
    int st=0;
    ll cnt1=0;
    ll cnt2=0;
    for(int i=1;i<=n;i++)//开始时有多少个要撞的 
    {
        if(c[i].x==0||c[i].x==L) continue;
        if(c[i].d>0) st++;
        else
        {
            if(st)
            {
                cnt1+=st;
            }
        }
    }
    sort(c+1,c+n+1,cmp3);//按d相同,x从小到大排,就是到达时间最短的牛 
    getT();
    for(int i=1;i<=n;i++) //T时刻的位置 
    {
        if(c[i].x==0||c[i].x==L) continue;
        if(c[i].d>0)
        {
            if(c[i].x+T>=L) c[i].cx=L;
            else    c[i].cx=c[i].x+T+0.1;
        }
        else
        {
            if(c[i].x-T<=0) c[i].cx=0;
            else    c[i].cx=c[i].x-T-0.1;
        }
    }
    sort(c+1,c+n+1,cmp2);
    st=0;
    for(int i=1;i<=n;i++)//T时刻有多少个要撞的 
    {
        if(c[i].cx==0||c[i].cx==L) continue;
        if(c[i].d>0) st++;
        else
        {
            if(st)
            {
                cnt2+=st;
            }
        }
    }
    cout<<cnt1-cnt2<<endl;
    return 0;
}
 

 

posted on 2020-03-03 22:29  Aminers  阅读(155)  评论(0编辑  收藏  举报

导航