BZOJ 3190 JLOI 2013 赛车 半平面交

75 篇文章 1 订阅
20 篇文章 0 订阅

每辆赛车有起始位置和速度,问哪些赛车在比赛过程中领先。

简直立了flag。。精度问题卡死我了。。

由s-t图像可得使用半平面交。

注意会有2两车的参数完全相同。要去重的时候把id也记录下来。

而且可以两辆车同时领先。

有些的斜率太相近。。结果atan2结果一样算法跪了。

我的算法应该是必开long double的。

下次用反三角一定要开long double。。。。。。

调了好久才发现这个问题。。


而且这道题好像是全字符比较?文尾有空格什么的会PE。


不过这道题也就我这么作死套半平面交模板233。

#include <cstdio>
#include <algorithm>
#include <list>
#include <cmath>
#define FOR(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int N = 50001;
typedef long double ld;
struct Point {
    ld x, y;
    Point(){}
    Point(ld _x, ld _y) : x(_x), y(_y) {}
    Point operator +(const Point &b) const { return Point(x + b.x, y + b.y); }
    Point operator -(const Point &b) const { return Point(x - b.x, y - b.y); }
    double operator *(const Point &b) const { return x * b.y - y * b.x; }
    Point operator *(double b) const { return Point(b * x, b * y); }
    bool operator ==(const Point &b) const { return x == b.x && y == b.y; }
} p[N];
 
struct Line {
    Point x, v;
    ld ang;
    list<int> id;
    Line(){}
    Line(const Point &_x, const Point &_v) : x(_x), v(_v), ang(atan2(_v.y, _v.x)) { }
 
    bool operator <(const Line &b) const {
        if (ang == b.ang) return v * (b.x - x) < 0;
        return ang < b.ang;
    }
 
    bool operator ==(const Line &b) const { return ang == b.ang; }
 
    Point intersection(const Line &b) {
        Point u = x - b.x;
        ld t = (b.v * u) / (v * b.v);
        return x + v * t;
    }
} l[N], q[N];
 
bool right(const Point &p, const Line &l) {
    return l.v * (p - l.x) < 0;
}
 
int main() {
    static int ans[N], k[N], v[N];
    int n, i, j, f = 1, r = 0, m = 0;
    scanf("%d", &n);
    FOR(i,1,n) scanf("%d", &k[i]);
    FOR(i,1,n) scanf("%d", &v[i]);
    FOR(i,1,n) l[i] = Line(Point(0, k[i]), Point(1, v[i])), l[i].id.push_back(i);
    l[++n] = Line(Point(0, 0), Point(0, -1));
    sort(l + 1, l + n + 1);
    q[++r] = l[1]; q[++r] = l[2];
    for (i = 3; i <= n; i++) {
        if (l[i].v == q[r].v) {
            if (l[i].x.y == q[r].x.y)
                q[r].id.merge(l[i].id);
        } else {
            while (f < r && right(q[r].intersection(q[r - 1]), l[i])) r--;
            q[++r] = l[i];
        }
    }
    for (i = f + 1; i <= r; i++)
        for (list<int>::iterator it = q[i].id.begin(); it != q[i].id.end(); it++) {
            ans[++m] = *it;
        }
    sort(ans + 1, ans + m + 1);
    printf("%d\n", m);
    for (i = 1; i <= m; i++) {
        printf("%d", ans[i]);
        if (i < m) putchar(' ');
    }
    return 0;
}

3190: [JLOI2013]赛车

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 1166   Solved: 373
[ Submit][ Status][ Discuss]

Description

 
这里有一辆赛车比赛正在进行,赛场上一共有N辆车,分别称为个g1,g2……gn。赛道是一条无限长的直线。最初,gi位于距离起跑线前进ki的位置。比赛开始后,车辆gi将会以vi单位每秒的恒定速度行驶。在这个比赛过程中,如果一辆赛车曾经处于领跑位置的话(即没有其他的赛车跑在他的前面),这辆赛车最后就可以得奖,而且比赛过程中不用担心相撞的问题。现在给出所有赛车的起始位置和速度,你的任务就是算出那些赛车将会得奖。
 

Input

第一行有一个正整数N表示赛车的个数。
接下来一行给出N个整数,按顺序给出N辆赛车的起始位置。
再接下来一行给出N个整数,按顺序给出N辆赛车的恒定速度。
 

Output

 
输出包括两行,第一行为获奖的赛车个数。
第二行按从小到大的顺序输出获奖赛车的编号,编号之间用空格隔开,注意最后一个编号后面不要加空格。
 
 

Sample Input


4
1 1 0 0
15 16 10 20

Sample Output


3
1 2 4

HINT

对于100%的数据N<=10000, 0<=ki<=10^9, 0<=vi<=10^9


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值