排位赛1-D Meetings

排位赛1-D Meetings

题目

Two barns are located at positions 0 and L on a one-dimensional number line. There are also N cows at distinct locations on this number line (think of the barns and cows effectively as points). Each cow i is initially located at some position xi and moving in a positive or negative direction at a speed of one unit per second, represented by an integer di that is either 1 or −1. Each cow also has a weight wi . All cows always move at a constant velocity until one of the following events occur: If cow i reaches a barn, then cow i stops moving. A meeting occurs when two cows i and j occupy the same point, where that point is not a barn. In this case, cow i is assigned cow j’s previous velocity and vice versa. Note that cows could potentially meet at points that are not integers. Let T be the earliest point in time when the sum of the weights of the cows that have stopped moving (due to reaching one of the barns) is at least half of the sum of the weights of all cows. Please determine the total number of meetings between pairs of cows during the range of time 0…T (including at time T).

题意

有n头奶牛站在长度为L的一维线上,谷仓位于0和L两个位置,每头奶牛会有体重wi和速度di,当两头奶牛相遇时它们会交换速度,奶牛进入谷仓就会停止运动,当进入谷仓的奶牛的体重之和大于等于所有奶牛体重之和的一半时记这时间点为T,问从0-T这段时间有多少对奶牛相遇。

解法

首先我们可以得知
1.一定是两端的奶牛先进入谷仓,再到中间的。
2.奶牛之间的相对位置是不变的,即假如奶牛的体重按坐标从小到大依次为7 6 5 4 3 2 8 10 ,无论什么时候奶牛的体重按坐标从小到大仍为7 6 5 4 3 2 8 10。
其实两头奶牛相遇时我们可以把他们看作时互相穿过只是体重交换了,所以当一头牛的速度方向和位置我们得知后它最终什么时候到哪个谷仓我们是可以算出来的,再结合上面的1和2我们可以得知进入谷仓时每头牛的体重,也就可以确定时间T了。
那现在我们只要求出0-T这段时间有多少对奶牛相遇就行了。
当我们得知每头牛的位置和速度方向时,我们可以求出会有多少对奶牛相遇,所以我们可以求出时间0(即初始状态)有多少对奶牛会相遇,再求出时间T后有多少对奶牛相遇,两个数值相减即答案。

代码:

#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
struct CC
{
	int w,x,v,t;
	double x1;
}a[50010],b[50010],c[50010];
int n,len,sum,ans,ans1,l,r,wight,sum_wight,m_i,time,s;

bool rmp(CC x,CC y) 
{
	if (x.x==y.x) return x.v>y.v;
	return x.x<y.x;
}

bool rmp1(CC x,CC y) 
{
	return x.t<y.t;
}

bool rmp2(CC x,CC y) 
{
	return x.x1<y.x1;
}

int main()
{
	scanf("%d%d",&n,&len);
	for (int i=1;i<=n;i++) 	
	{
		scanf("%d%d%d",&a[i].w,&a[i].x,&a[i].v);
		sum_wight+=a[i].w;
	}
	sort(a+1,a+n+1,rmp);
	for (int i=1;i<=n;i++) if (a[i].v==1) sum++; else ans+=sum;
	for (int i=1;i<=n;i++) 
	{
		if (a[i].v==-1) b[i].t=a[i].x; else b[i].t=len-a[i].x;
		b[i].x=a[i].x;
		b[i].v=a[i].v;
	}
	sort(b+1,b+n+1,rmp1);
	l=1;r=n;
	for (int i=1;i<=n;i++) 
	{
		if (b[i].v==1) 
		{
			wight+=a[r].w;
			r--;
		} else 
		{
			wight+=a[l].w;
			l++;
		}
		if (wight*2>=sum_wight) 
		{
			m_i=i+1;
			time=b[i].t;
			break;
		}
	}
	for (int i=m_i;i<=n;i++) 
	if (b[i].t>time)
	{
		s++;
		if (b[i].v==1) c[s].x1=b[i].x+time+0.1; else c[s].x1=b[i].x-time-0.1; //因为要算T后有多少对牛会相遇所以时间上要加0.1
		c[s].v=b[i].v;
	}
	sort(c+1,c+s+1,rmp2);
	sum=0;
	for (int i=1;i<=s;i++) if (c[i].v==1) sum++; else ans1+=sum;
	printf("%d",ans-ans1);
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值