题解 | #[JLOI2013]赛车#

[JLOI2013]赛车

https://ac.nowcoder.com/acm/problem/20137

半平面交模板题 不了解的可以去学习一下~

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
const int maxn = 10010;
const long double eps = 1e-18;
#define x first
#define y second
typedef long double LD;
typedef pair<LD, LD> PDD;
typedef pair<int,int> PII;
typedef struct node
{
    PDD st, ed;
    vector<int> ids;
}Line;
Line lines[maxn];
int ki[maxn], vi[maxn];
int q[maxn], ans[maxn];
int n, cnt;
PDD operator - (PDD a, PDD b)
{
    return {a.x - b.x, a.y - b.y};
}
int sign(LD x)
{
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    return 1;
}
int dcmp(LD x, LD y)
{
    if(fabs(x - y) < eps) return 0;
    if(x < y) return -1;
    return 1;
}
LD cross(PDD a, PDD b)
{
    return a.x * b.y - a.y * b.x;
}
LD area(PDD a, PDD b, PDD c)
{
    return cross(b - a, c - a);
}
LD get_angle(Line a)
{
    return atan2(a.ed.y - a.st.y, a.ed.x - a.st.x);
}
bool cmp(const Line &a, const Line &b)
{
    LD thetaA = get_angle(a), thetaB = get_angle(b);
    if(!dcmp(thetaA, thetaB)) return area(a.st, a.ed, b.ed) < 0;
    return thetaA < thetaB;
}
PDD get_line_intersection(PDD p, PDD v, PDD q, PDD w)
{
    auto u = p - q;
    LD t = cross(w, u) / cross(v, w);
    return {p.x + t * v.x, p.y + t * v.y};
}
PDD get_line_intersection(Line a, Line b)
{
    return get_line_intersection(a.st, a.ed - a.st, b.st, b.ed - b.st);
}
bool on_right(Line a, Line b, Line c)
{
    auto o = get_line_intersection(b, c);
    return area(a.st, a.ed, o) < 0;
}
void half_plane_intersection()
{
    sort(lines, lines + cnt, cmp);
    int hh = 0, tt = -1;
    for(int i = 0; i < cnt; i ++){
        if(i && !dcmp(get_angle(lines[i]), get_angle(lines[i - 1]))) continue;
        while(hh + 1 <= tt && on_right(lines[i], lines[q[tt - 1]], lines[q[tt]])) tt --;
        while(hh + 1 <= tt && on_right(lines[i], lines[q[hh]], lines[q[hh + 1]])) hh ++;
        q[++ tt] = i;
    }
    while(hh + 1 <= tt && on_right(lines[q[hh]], lines[q[tt - 1]], lines[q[tt]])) tt --;
    while(hh + 1 <= tt && on_right(lines[q[tt]], lines[q[hh]], lines[q[hh + 1]])) hh ++;
    int k = 0;
    for(int i = hh; i <= tt; i ++){
        for(auto id : lines[q[i]].ids){
            ans[k ++] = id;
        }
    }
    sort(ans, ans + k);
    cout << k << endl;
    for(int i = 0; i < k; i ++) cout << ans[i] + 1 << ' ';
    cout << endl;
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n;
    map<PII, vector<int>> mp;
    for(int i = 0; i < n; i ++) cin >> ki[i];
    for(int i = 0; i < n; i ++) cin >> vi[i];
    for(int i = 0; i < n; i ++){
        mp[{ki[i], vi[i]}].push_back(i);
    }
    lines[cnt ++] = {{0, 10000}, {0, 0}};
    lines[cnt ++] = {{0, 0}, {10000, 0}};
    for(auto [k, v] : mp){
        lines[cnt ++] = {{0, k.x}, {1, k.x + k.y}, v};
    }
    half_plane_intersection();
    return 0;
}
全部评论

相关推荐

预计下个星期就能开奖吧,哪位老哥来给个准信
华孝子爱信等:对接人上周说的是这周
投递华为等公司10个岗位 >
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务