2020.2.19GDUT寒假训练排位赛1-D

D — Circular Dance

题目大意:

两个谷仓位于一维数轴上的位置0和L(1≤L≤109)。也有N头牛(1≤N≤5*104)在不同的地点在数轴上的。每头奶牛i最初位于xi的某个位置,以每秒1单位的速度向正或负方向移动,用整数di表示,di为1或- 1。每头奶牛的体重wi也在范围[1,103]内。所有的奶牛总是以恒定的速度移动,直到下列事件之一发生:如果奶牛i到达谷仓,那么奶牛i停止移动。当两头牛i和j占据了同一个地方,而那个地方不是谷仓时,在这种情况下,奶牛i与j速度交换。注意,奶牛可能会在非整数的点相遇。
当进入谷仓的所有牛的重量之和至少是所有牛的重量之和的一半时,所用时间记为T。请确定在时间0…T范围内(包括时间T),两对牛的总相遇次数。
输入
第一行包含两个以空格分隔的整数N和L。
接下来的N行分别包含三个以空格分隔的整数wi、xi和di。所有的位置xi都是不同的,并且满足0 输出
只有一行,相遇对数。
在这里插入图片描述

题目分析:

两头奶牛相遇时交换速度可以看作互相穿过交换体重了,所以向左的有几头牛,最后就有几头牛归向0,向右的有几头牛,最后就有几头牛归向L。所以,对位置排序的奶牛,如果有n头牛,x头牛向左走,y头牛向右走。那么前x个重量一定会归向0位置,后y个重量会归为L位置。离谷仓最近的奶牛肯定先进,就可以算出时间T了。算出在无限时间的相遇对数和T内未相遇的对数,两个数值相减即答案。

代码实现:

#include 
#include 
#include 
using namespace std;

struct cow
{
	int w,x,d,t;
	double x1;
}a[50010],b[50010],c[50010];

bool cmp1(cow x,cow y)
{
	if (x.x==y.x) return x.d>y.d;
	return x.x<y.x;
}

bool cmp2(cow x,cow y)
{
	return x.t<y.t;
}

bool cmp3(cow x,cow y)
{
	return x.x1<y.x1;
}

int main()
{
    int n,len;
    int ans = 0, ans0 = 0;
    int sum = 0, sum_wight = 0, wight = 0;
    int m_i = 0, s = 0;
    int time = 0;
    int l,r;
	scanf("%d%d",&n,&len);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d", &a[i].w, &a[i].x, &a[i].d);
		sum_wight += a[i].w;
	}
	sort(a+1,a+n+1,cmp1);
	for(int i=1; i<=n; i++){	//无限时间相遇次数ans
        if(a[i].d==1) sum++;
        else ans += sum;
	}
	for(int i=1; i<=n; i++)	//为了找出先进入谷仓的重量
	{
		if(a[i].d==-1) b[i].t = a[i].x;
		else b[i].t = len-a[i].x;
		b[i].x = a[i].x;
		b[i].d = a[i].d;
	}
	sort(b+1,b+n+1,cmp2);	//排序,越靠前越先进入谷仓
	l = 1;
	r = n;
	for(int i=1; i<=n; i++)	//算出时间T,即time
	{
		if(b[i].d==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].d==1) c[s].x1 = b[i].x+time+0.1;	//错开相遇点
            else c[s].x1 = b[i].x-time-0.1;
            c[s].d = b[i].d;
        }
    }
	sort(c+1,c+s+1,cmp3);
	sum = 0;
	for(int i=1; i<=s; i++){
        if(c[i].d==1) sum++;
        else ans0 += sum;
	}
	printf("%d\n",ans-ans0);
	return 0;
}

最后希望路过的dl给予改进建议!

你可能感兴趣的:(2020.2.19GDUT寒假训练排位赛1-D)