【2015-2016 ACM-ICPC, NEERC, Southern Subregional Contest D】【模拟 讨论】Boulevard 人流行走看是否相交 beautiful code

来源:互联网 发布:外墙线条展开面积算法 编辑:程序博客网 时间:2024/05/16 10:10

D. Boulevard
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Welcoming autumn evening is the best for walking along the boulevard and n people decided to do so.

The boulevard can be represented as the axis Ox. For every person there are three parameters characterizing the behavior: ti, si, fi — the moment of time when the i-th person starts walking, the start point and the end point of the walk respectively. Each person moves in a straight line along the boulevard from si to fi with a constant speed of either 1 or  - 1 depending on the direction.

When the i-th person appears on the boulevard at the point si she immediately starts walking towards the point fi.

If two or more persons meet at the boulevard (they are at the same point at the same time, no matter which directions they are going) they all greet each other. Like in the normal life, every pair of people greet each other at most once.

You task is to calculate for every person how many people she greets while walking along the boulevard.

Please, pay attention to the fact that i-th person may meet and greet any other person at points si and fi. After a person achieves the destination point fi she moves out of the boulevard and cannot greet anyone else. The same rule applies to the start of the walk: a person cannot greet anyone until she appears on the boulevard.

Input

In the first line there is an integer n (2 ≤ n ≤ 1000) — the number of people who decided to go for a walk.

The following n lines contain parameters for n people. In the i-th line there are three positive integers ti, si, fi(1 ≤ ti, si, fi ≤ 106,  si ≠ fi), where ti, si, fi — the moment of time when the i-th person starts walking, the start point and the end point of the walk respectively.

Output

The single line of the output should contain a sequence of n integers r1, r2, ..., rn separated by a space, where ri denotes the number which the i-th person greets other people while walking along the boulevard.

Sample test(s)
input
31 1 105 8 29 9 10
output
2 1 1 
input
33 2 44 3 43 6 4
output
2 2 2 



第一种比较笨重的做法

#include<stdio.h> #include<string.h>#include<ctype.h>#include<math.h>#include<iostream>#include<string>#include<set>#include<map>#include<vector>#include<queue>#include<bitset>#include<algorithm>#include<time.h>using namespace std;void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}#define MS(x,y) memset(x,y,sizeof(x))#define MC(x,y) memcpy(x,y,sizeof(x))#define MP(x,y) make_pair(x,y)#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}const int N=1010,M=0,Z=1e9+7,ms63=1061109567;int casenum,casei;int n;struct A{int t,st,ed,t2,typ,o;bool operator < (const A& b)const {return t<b.t;}}a[N];int v[N];int main(){while(~scanf("%d",&n)){for(int i=1;i<=n;i++){scanf("%d%d%d",&a[i].t,&a[i].st,&a[i].ed);a[i].t2=a[i].t+abs(a[i].ed-a[i].st);a[i].typ=a[i].st<a[i].ed?1:-1;a[i].o=i;}sort(a+1,a+n+1);MS(v,0);for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++)if(a[i].t2>=a[j].t){int t=a[j].t-a[i].t;//求出时间差int p=a[i].st+a[i].typ*t;//求出经过这个时间差后第一个人的位置if(p==a[j].st){++v[a[i].o];++v[a[j].o];continue;}if(a[i].typ==a[j].typ)continue;if(a[i].typ==1&&p<=a[j].st)//如果i右走,j就必定向左走{t=min(a[i].t2,a[j].t2)-a[j].t;int p1=p+t;int p2=a[j].st-t;if(p1>=p2){++v[a[i].o];++v[a[j].o];}}if(a[i].typ==-1&&p>=a[j].st)//如果i左走,j就必定向右走{t=min(a[i].t2,a[j].t2)-a[j].t;int p1=p-t;int p2=a[j].st+t;if(p1<=p2){++v[a[i].o];++v[a[j].o];}}}}for(int i=1;i<=n;i++)printf("%d ",v[i]);puts("");}return 0;}/*【trick&&吐槽】我是傻叉,既然把人都排序过了,那编号对应也不一样了。映射要映射到人的编号上,细节要十分注意啊啊啊啊!【题意】有n([2,1000])个人去散步,每个人都始终保持这1m/s的速度每个人有三个参数t[i],st[i],ed[i],st[i]!=ed[i]t[i]表示第i个人开始散步的时间.st[i]、ed[i]分别表示第i个人走路的起点和终点我们想输出每个人分别与其他几个人打招呼。(t[i],st[],ed[]都是1e6范围的数)【类型】暴力【分析】我们发现,这题小的是n,于是我们直接枚举每两个人,看看他俩是否打过招呼即可!具体如何实现呢?1,我们要按照时间的早晚排序,对于每个pair(先出发的人i,后出发的人j)2,i的结束时间要比j的开始时间要晚3,i先要到达j的出发时间,如果位置一样,那肯定可以打招呼4,现在两个人方向必须相逆,然后必须在现阶段越走越近5,我们求出两个人同时在场的最晚时间6,求出最晚时间下的两个人的位置,如果发生了交错,那说明打了招呼【时间复杂度&&优化】O(n^2)*/


第二种比较优美的做法

#include<stdio.h> #include<string.h>#include<ctype.h>#include<math.h>#include<iostream>#include<string>#include<set>#include<map>#include<vector>#include<queue>#include<bitset>#include<algorithm>#include<time.h>using namespace std;void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}#define MS(x,y) memset(x,y,sizeof(x))#define MC(x,y) memcpy(x,y,sizeof(x))#define MP(x,y) make_pair(x,y)#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}const int N=1010,M=0,Z=1e9+7,ms63=1061109567;int casenum,casei;int n;struct A{int t1,t2,st,ed,typ;}a[N];int v[N];int main(){while(~scanf("%d",&n)){for(int i=1;i<=n;i++){scanf("%d%d%d",&a[i].t1,&a[i].st,&a[i].ed);a[i].t2=a[i].t1+abs(a[i].ed-a[i].st);a[i].typ=a[i].st<a[i].ed?1:-1;}MS(v,0);for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){int t1=max(a[i].t1,a[j].t1);int t2=min(a[i].t2,a[j].t2);if(t1>t2)continue;LL pi1=a[i].st+(t1-a[i].t1)*a[i].typ;LL pi2=a[i].st+(t2-a[i].t1)*a[i].typ;LL pj1=a[j].st+(t1-a[j].t1)*a[j].typ;LL pj2=a[j].st+(t2-a[j].t1)*a[j].typ;if((pi1-pj1)*(pi2-pj2)<=0){++v[i];++v[j];}}}for(int i=1;i<=n;i++)printf("%d ",v[i]);puts("");}return 0;}/*【trick&&吐槽】我是傻叉,既然把人都排序过了,那编号对应也不一样了。映射要映射到人的编号上,细节要十分注意啊啊啊啊!【题意】有n([2,1000])个人去散步,每个人都始终保持这1m/s的速度每个人有三个参数t[i],st[i],ed[i],st[i]!=ed[i]t[i]表示第i个人开始散步的时间.st[i]、ed[i]分别表示第i个人走路的起点和终点我们想输出每个人分别与其他几个人打招呼。(t[i],st[],ed[]都是1e6范围的数)【类型】暴力【分析】我们发现,这题小的是n,于是我们直接枚举每两个人,看看他俩是否打过招呼即可!具体如何实现呢?1,我们要按照时间的早晚排序,对于每个pair(先出发的人i,后出发的人j)2,i的结束时间要比j的开始时间要晚3,i先要到达j的出发时间,如果位置一样,那肯定可以打招呼4,现在两个人方向必须相逆,然后必须在现阶段越走越近5,我们求出两个人同时在场的最晚时间6,求出最晚时间下的两个人的位置,如果发生了交错,那说明打了招呼其实总结起来,就是找出两个人都在的条件下的最早时间和最晚时间。然后看位置大小关系是否发生过错位。于是我们引入更优美的代码——直接求出两个人共存时间下的(i位置1,j位置1)和(i位置2,j位置2),然后用乘法<=0判定即可。【时间复杂度&&优化】O(n^2)*/


1 0
原创粉丝点击