【NOIP模拟】Route

                                                 Route

题目描述

一条直线上有 n 个人在走,有三个值来描述第i个人的行为:t[i],s[i],f[i],分别表示他出发的时间,他的起点位置和终点位置。假设每个人走的一样快,他们每个单位时间只会朝目的地走一个单位的距离。

当两个人相遇的时候,他们相互之间会打招呼。按照常理,两个人之间最多只会打一次招呼。

请算出每个人在他的旅程中要和多少个人打招呼。

注意:
(1)某个人在出发前是不在直线上的;
(2)到终点后,这个人也不再出现在直线上;
(3)如果 2 个人在同一个位置、同一时刻出发,属于相遇的情况。

输入格式

输入第一行包括一个整数 n 表示人数。
接下来 n 行,每行三个整数 t[i],s[i],f[i]。

输出格式

一行 n 个整数。第 i 个整数 a[i] 表示第 i 个人总共要和 a[i] 个人(总人数)打招呼。

样例数据 1

输入


1 1 10 
5 8 2 
9 9 10

输出

2 1 1

备注

【样例说明】

【数据范围】
对 30% 的输入数据 :n≤10
对 100% 的输入数据 :n≤1000,1≤t[i],s[i],f[i]≤1000000,s[i]≠f[i]

解析:

        题很简单,然而在考场上仍然想复杂了。。。

        枚举每对人,我们只需要分同向与反向各讨论一下就行了。正向的情况只要是先出发的人到达后出发的人的端点时刚好后出发的人出发说明就能碰上,否则不能。反向的情况我们只需要解一个一元一次方程就行了。

代码:

#include <bits/stdc++.h>
using namespace std;

const int Max=10010;
int n,m,l,r,mid;
int sum[Max];
//f起始时间,s t 起点终点 
struct shu{int f,s,t,flag,id;};
shu num[Max];
int ans[Max];

inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') {f=-1;c=getchar();}
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}

inline bool comp(const shu &a,const shu &b)
{
   if(a.f != b.f) return a.f < b.f;
   if(a.s != b.s) return a.s < b.s;
   return a.t < b.t;
}

inline int calc1(int a,int b)
{
   double t = (double)(num[b].s - num[b].f * num[b].flag + num[a].f * num[a].flag - num[a].s) / (double)(num[a].flag - num[b].flag);
   if(t >= 0 && t >= (double)(num[a].f) && t >= (double)(num[b].f) && t<(double)(num[a].f + abs(num[a].t - num[a].s)) &&t < (double)(num[b].f + abs(num[b].t - num[b].s))) return 1;
   else return 0;
}

inline int calc2(int a,int b)
{
   if(num[a].flag == 1)
   {
   	 int posa = num[a].s + num[b].f - num[a].f;
   	 if(posa == num[b].s && posa <= num[a].t) return 1;
   	 else return 0;
   }
   else
   {
   	 int posa = num[a].s - (num[b].f - num[a].f);
   	 if(posa == num[b].s && posa >= num[a].t) return 1;
   	 else return 0;
   }
}

inline void solve()
{
   for(register int i=1;i<=n-1;i++)
   	 for(register int j=i+1;j<=n;j++)
   	 {
   	   if(num[i].s == num[j].s && num[i].f == num[j].f) {sum[i]++,sum[j]++;continue;}   //开始就相遇
   	   if(num[i].flag != num[j].flag)
   	   {
   	     if(calc1(i,j)) sum[i]++,sum[j]++;
   	   }
   	   else
   	   {
   	   	 if(calc2(i,j)) sum[i]++,sum[j]++;
   	   }
   	 }
}

int main()
{
	n=get_int();
	for(int i=1;i<=n;i++)
	{
	   num[i].f=get_int();
	   num[i].s=get_int();
	   num[i].t=get_int();
	   num[i].id=i;
	   num[i].s > num[i].t ? num[i].flag = -1 : num[i].flag = 1;
	}
    sort(num+1,num+n+1,comp);
	solve();
	for(int i=1;i<=n;i++) ans[num[i].id] = sum[i];
	for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38083668/article/details/81173845