CodeForces 589D --- D. Boulevard (数学题目--枚举分类讨论)

78 篇文章 0 订阅
49 篇文章 0 订阅

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.

Examples

Input

3
1 1 10
5 8 2
9 9 10

Output

2 1 1

Input

3
3 2 4
4 3 4
3 6 4

Output

2 2 2 

大体题意:有n个人走在林荫大道,告诉你每个人出现的时间,起始位置,终止位置,求出每一个人最多和几个人相遇,两个人最多相遇一次,他们的速度是±1.

思路:整体思路很好想,枚举每一个人,在来一重循环,枚举他能相遇的人,如果能的ans[i]++,最后输出ans即可!
关键就在于判断相遇的函数!
我想的比较麻烦,稍微看看吧。
我把他们分成了两个线段,两个线段分成了三种情况,两个线段外离,相交,内含!
分别讨论即可! 外离肯定不相遇,相交四种方向讨论一下,内含四种情况讨论一下
其实分类讨论 讨论方向就行了,如果他们同向的话,要想相遇只能在另一个人开始的地方相遇!
如果相向的话,就可以设出相遇位置为X,解方程即可!

详细见代码:

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

struct Node{
    int t,s,e;
    int dir;
}p[1007];
int ans[1007];
bool rev(int id1,int id2){
    int t1 = p[id1].t,s1 = p[id1].s,e1 = p[id1].e;
    int t2 = p[id2].t,s2 = p[id2].s,e2 = p[id2].e;
    int mins = min(s1,e1),maxs = max(s1,e1);
    int mins2 = min(s2,e2),maxs2 = max(s2,e2);
    if (!(mins < mins2 || (mins == mins2  && maxs > maxs2)) )swap(id1,id2);
    t1 = p[id1].t,s1 = p[id1].s,e1 = p[id1].e;
    t2 = p[id2].t,s2 = p[id2].s,e2 = p[id2].e;
    int dir1 = p[id1].dir;
    int dir2 = p[id2].dir;
    mins = min(s1,e1),maxs = max(s1,e1);
    mins2 = min(s2,e2),maxs2 = max(s2,e2);
    if (maxs < mins2)return 0;
    if (maxs == mins2){
        if (dir1 == 1 && dir2 == 1){ // OK
            return e1-s1+t1 == t2;
        }
        if (dir1 == 1 && dir2 == -1){ // OK
            return e1-s1+t1 == s2-e2+t2;
        }
        if (dir1 == -1 && dir2 == 1){ // OK
            return t1 == t2;
        }
        if (dir1 == -1 && dir2 == -1){ // OK
            return t1 == s2-e2+t2;
        }

    }

    if (mins2 < maxs && maxs2 > maxs){
        if (dir1 == 1 && dir2 == 1){ // OK
            return s2-s1+t1 == t2;
        }
        if (dir1 == 1 &&dir2 == -1){ // OK
            double t = (s2+t2+s1-t1)*1.0/2;
            if (t >=e2 && t <= e1)return 1;
            return 0;
        }
        if (dir1 == -1 && dir2 == 1){//ok
            double t = s1 + t1 + s2 - t2;
            t/=2;
            if (t >= s2 && t <= s1)return 1;
            return 0;
        }
        if (dir1 == -1 && dir2 ==-1){//ok
            return t1 == s2-s1+t2;
        }
    }


    if (dir1 == 1 && dir2 == 1){ // OK!
        return s2-s1+t1 == t2;
    }
    if (dir1 == 1 && dir2 == -1){ // OK!
        double t = s2+t2+s1-t1;
        t/=2.0;

        if (t >= e2 && t <= s2)return 1;
        return 0;
    }
    if (dir1 == -1 &&  dir2 == 1){ // OK
        double t = s1+t1+s2-t2;
        t/=2.0;
        if (t >= s2 && t <= e2)return 1;
        return 0;

    }
    if (dir1 == -1 && dir2 == -1){ // OK
        return t2 == s1-s2+t1;
    }

}
int main(){
    int n;
    scanf("%d",&n);
    for (int i = 0; i < n ;++i){
        scanf("%d %d %d",&p[i].t,&p[i].s,&p[i].e);
        if (p[i].e > p[i].s)p[i].dir = 1;
        else p[i].dir = -1;

    }
    for (int i = 0; i < n; ++i){
        for (int j = 0; j < n; ++j){
            if(i == j)continue;
            if (rev(i,j))ans[i] ++;
        }
    }
    for (int i = 0 ; i < n; ++i){
        if (i)printf(" ");
        printf("%d",ans[i]);
    }
    puts("");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值