【线段树二分】第十三届蓝桥杯省赛C++ A组/研究生组 Python 研究生组《扫描游戏》(C++)

news2024/11/18 13:42:18

【题目描述】

有一根围绕原点 O 顺时针旋转的棒 OA,初始时指向正上方(Y 轴正向)。

在平面中有若干物件,第 i 个物件的坐标为(x_{i},y_{i}),价值为 z_{i}

当棒扫到某个物件时,棒的长度会瞬间增长 z_{i},且物件瞬间消失(棒的顶端恰好碰到物件也视为扫到),如果此时增长完的棒又额外碰到了其他物件,也按上述方式消去(它和上述那个点视为同时消失)。

如果将物件按照消失的时间排序,则每个物件有一个排名,同时消失的物件排名相同,请输出每个物件的排名,如果物件永远不会消失则输出 −1。

所有物品坐标两两不同。

【输入格式】

输入第一行包含两个整数 n、L,用一个空格分隔,分别表示物件数量和棒的初始长度。

接下来 n 行每行包含第三个整数x_{i},y_{i}z_{i}

【输出格式】

输出一行包含 n 整数,相邻两个整数间用一个空格分隔,依次表示每个物件的排名。

【数据范围】

对于 30% 的评测用例,1≤n≤500;
对于 60% 的评测用例,1≤n≤5000;
对于所有评测用例,1≤n≤200000,−10^{9} ≤ x_{i},y_{i} ≤ 10^{9},1 ≤ L,z_{i} ≤ 10^{9}

【输入样例】

5 2
0 1 1
0 3 2
4 3 5
6 8 1
-51 -33 2

【输出样例】

1 1 3 4 -1

【思路】

题解来源:AcWing 4649. 扫描游戏 - AcWing

【代码】

#include <bits/stdc++.h>
typedef long long LL;
const int N = 2e5 + 10;
const __int128 INF = 1e38;
int n, ans[N], idx;
__int128 len;

template <typename T> //快读模板
inline T fastread(T &x)
{
    x = 0;
    T w = 1;
    char ch = 0;
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = x * 10 + (ch - '0');
        ch = getchar();
    }
    return x = x * w;
}

struct point
{
    LL x, y, z;
    int id;
} a[N];
int Quadrant(point a) //因为棒是顺时针旋转,我们这里把正常意义下的二四象限调换一下
{
    if (a.x >= 0 && a.y > 0)
        return 1;
    if (a.x > 0 && a.y <= 0)
        return 2;
    if (a.x <= 0 && a.y < 0)
        return 3;
    else
        return 4;
}
LL cross(point a, point b) //求叉积
{
    return a.x * b.y - a.y * b.x;
}
bool cmp(point a, point b) //极角排序,排序完后,所有点就按顺时针排好了
{
    if (Quadrant(a) == Quadrant(b))
    {
        if (cross(a, b) == 0) //当极角相同,我们这里按照距离原点距离的平方来排序
            return a.x * a.x + a.y * a.y < b.x * b.x + b.y * b.y;
        return cross(a, b) < 0;
    }
    return Quadrant(a) < Quadrant(b);
}

//线段树
struct
{
    __int128 minv;
} seg[N * 4]; //线段树维护的是点到原点的距离的区间最小值
void pushup(int id)
{
    seg[id].minv = std::min(seg[id << 1].minv, seg[id << 1 | 1].minv);
}
void build(int id, int l, int r)
{
    if (l == r)
        seg[id].minv = a[l].x * a[l].x + a[l].y * a[l].y;
    else
    {
        int mid = l + r >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
        pushup(id);
    }
}
void change(int id, int l, int r, int pos, __int128 val)
{
    if (l == r)
        seg[id].minv = val;
    else
    {
        int mid = l + r >> 1;
        if (pos <= mid)
            change(id << 1, l, mid, pos, val);
        else
            change(id << 1 | 1, mid + 1, r, pos, val);
        pushup(id);
    }
}
int search(int id, int l, int r, int ql, int qr, __int128 val) //线段树上二分模板
//返回[ql,qr]这段区间里从左至右第一个小于等于val的元素的下标,不存在就返回-1
{
    if (l == ql && r == qr) //此时的区间正好是询问区间
    {
        if (seg[id].minv > val) //如果整个区间的最小值都大于val,直接返回-1
            return -1;
        else
        {
            if (l == r)
                return l;
            int mid = l + r >> 1;
            if (seg[id << 1].minv <= val) //如果左儿子里有这样的元素,直接进入左儿子即可
                return search(id << 1, l, mid, ql, mid, val);
            else //否则进入右儿子
                return search(id << 1 | 1, mid + 1, r, mid + 1, qr, val);
        }
        return seg[id].minv;
    }
    int mid = l + r >> 1;
    if (qr <= mid)
        return search(id << 1, l, mid, ql, qr, val);
    else if (ql > mid)
        return search(id << 1 | 1, mid + 1, r, ql, qr, val);
    else
    {
        int pos = search(id << 1, l, mid, ql, mid, val);
        if (pos == -1)
            return search(id << 1 | 1, mid + 1, r, mid + 1, qr, val);
        else
            return pos;
    }
}
signed main()
{
    // 注意用了快读就不能关闭流同步,不然大概率会炸
    fastread(n), fastread(len);
    for (int i = 1; i <= n; ++i) //初始化ans数组
        ans[i] = -1;
    for (int i = 1; i <= n; ++i)
    {
        fastread(a[i].x), fastread(a[i].y), fastread(a[i].z);
        a[i].id = i;
    }
    std::sort(a + 1, a + n + 1, cmp);
    build(1, 1, n);
    int last = 0;     // last维护上一个扫到的点
    int rank = 0;     // rank记录扫到点的排名
    int lastrank = 0; // 维护lastrank主要是为了处理有几个点极角相同的特殊情况,根据题意它们的排名相同
    while (true)
    {
        int idx = -1;
        if (last + 1 <= n) //一定要记得这句if
            idx = search(1, 1, n, last + 1, n, len * len);
        if (idx != -1)
            len += a[idx].z;
        else
        {
            if (last >= 2) //一定要记得这句if
                idx = search(1, 1, n, 1, last - 1, len * len);
            if (idx != -1)
                len += a[idx].z;
        }
        if (idx == -1) //没能找到可以划到的点,退出死循环
            break;
        change(1, 1, n, idx, INF); //对于扫过的点,我们可以把它单点修改成无穷大,等价于它消失了
        if (last == 0)
            ans[a[idx].id] = ++rank, lastrank = rank;
        else
        {
            if (Quadrant(a[last]) == Quadrant(a[idx]) && cross(a[last], a[idx]) == 0) //该点和上一个点是同时被扫到的,所以排名要一样
                ans[a[idx].id] = lastrank, ++rank;
            else
                ans[a[idx].id] = ++rank, lastrank = rank;
        }
        last = idx;
    }
    for (int i = 1; i <= n; ++i)
        printf("%d ", ans[i]);
    printf("\n");
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1548118.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FreeRTOS的介绍

FreeRTOS介绍 本文主要涉及RTOS的相关内容 1.RTOS与裸机的区别 2.RTOS的架构与特点 3.任务调度 4.任务状态 文章目录 FreeRTOS介绍一、RTOS与裸机的区别二、FreeRTOS 简介2.1 特点2.2 架构2.3 应用领域总结 三、 任务调度3.1 基本原理3.2 调度策略3.3 实现方式 四、 任务状态 一…

spring cloud 限流熔断配置

springcloud 微服务网关 zuul.strip-prefixtrue zuul.routes.postgres-client.path /ps01/** zuul.routes.postgres-client.service-idpostgres-client zuul.routes.postgres-client02.path/ps02/** zuul.routes.postgres-client02.service-idpostgres-client02 zuul.semaphor…

主流公链 - BSC

探索Binance Smart Chain (BSC) 区块链&#xff1a;实现高性能的智能合约平台 1. BSC 简介 Binance Smart Chain (BSC)是由全球领先的加密货币交易平台币安&#xff08;Binance&#xff09;推出的智能合约平台。它旨在为开发者提供高性能、低成本的区块链基础设施&#xff0c;…

助力福建新型职业农民培育 北方天途推进无人机植保应用培训

为加强新型职业农民的职业培育&#xff0c;扩展新型农民的知识范围和专业技术水平&#xff0c;推进农业供给侧结构性改革。日前&#xff0c;在农业部门的大力支持下&#xff0c;北方天途航空和宁德天禾科技服务携手为福建省农民朋友开展了植保无人机驾驶员的应用培训。福建省农…

数据分析面试题(41~50)

41、lstm的原理、lstm和rnn的区别 ①LSTM是一种常用于处理序列数据的循环神经网络&#xff08;RNN&#xff09;架构&#xff0c;特别适用于长序列的建模。其主要特点是通过门控机制来控制信息的流动&#xff0c;从而有效地解决了传统RNN在处理长序列时的梯度消失或爆炸的问题。…

【Java程序设计】【C00374】基于(JavaWeb)Springboot的社区疫情管理系统(有论文)

TOC 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;博客中有上百套程序可供参考&#xff0c;欢迎共同交流学习。 项目简介 项目获取 &#x1f345;文末点击卡片…

【数据分享】1929-2023年全球站点的逐日平均压力(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 有关气象指标的监测站点数据&#xff0c;之前我们分享过1929-2023年全球气象站…

【gitee】设置忽略文件.gitignore的方法

已经提交在 gitee 上的文件&#xff0c;再设置忽略文件.gitignore&#xff0c;怎么成立 忽略已经提交的文件&#xff0c;可以使用以下命令将这些文件从Git中移除&#xff08;但是保留在本地文件系统中&#xff09;&#xff1a; git rm --cached <file_name>//例&#x…

揭秘YouTube视频世界:利用Python和Beautiful Soup的独特技术

介绍 YouTube作为全球最大的视频分享平台&#xff0c;每天有数以亿计的视频被上传和观看。对于数据分析师、市场营销人员和内容创作者来说&#xff0c;能够获取YouTube视频的相关数据&#xff08;如标题、观看次数、喜欢和不喜欢的数量等&#xff09;是非常有价值的。本文将介…

iOS - Runtime - Class的结构

文章目录 iOS - Runtime - Class的结构前言1. Class的结构1.1 Class的结构1.1.1 objc_class1.1.2 class_rw_t1.1.3 class_ro_t 1.2 class_rw_t和class_ro_t的区别1.3 class_rw_t和class_ro_t的关系1.3.1 分析关系1.3.2 原因 1.4 method_t1.4.1 Type Encoding1.4.2 types iOS - …

双亲委派机制总结

回顾了一下双亲委派机制&#xff0c;在这记录记录&#xff0c;下一篇会基于打破双亲委派机制来更新 1. 类加载&#xff1a; 多个java文件经过编译打包后生成可运行jar包&#xff0c;最后启动程序。首先需要通过类加载器把主类加载到JVM。主类在运行过程中如果使用到其他类&a…

Spring Boot 整合分布式搜索引擎 Elastic Search 实现 自动补全功能

文章目录 ⛄引言一、分词器⛅拼音分词器⚡自定义分词器 二、自动补全查询三、自动补全⌚业务需求⏰实现酒店搜索自动补全 四、效果图⛵小结 ⛄引言 本文参考黑马 分布式Elastic search Elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;…

华为云服务器租用价格_云服务器优惠活动_2024年新版报价

2024年华为云服务器租用价格表&#xff0c;云服务器优惠价格35元一年&#xff0c;配置为1核2G1M带宽HECS云服务器、L实例-2核2G3M配置46元1年、4核16G10M华为云服务器24元一个月、2核4G5M服务器158元一年&#xff0c;3年1010元、华为云香港服务器99元一年、增强型C7云服务器4核…

ReActor丨一文教你学会用Stable Diffusion插件换脸

本教程将带您了解如何下载和使用 stable diffusion 的 ReActor扩展&#xff0c;实现完美的换脸效果。 ReActor 是一个强大的工具&#xff0c;允许您无缝地交换面孔并获得逼真的效果。 无论您是艺术家、内容创作者&#xff0c;还是仅仅想要体验图像操作的乐趣&#xff0c;这份…

纯前端网页播放20路海康威视、大华RTSP视频流,调用双显卡GPU加速

关于网页播放摄像头RTSP视频流&#xff0c;网上有很多免费开源方案&#xff0c;大多数是通过把在服务器端RTSP转码成HLS或者RTMP等前端可以播放的视频流&#xff0c;然后推到前端播放&#xff0c;但是大多数延迟非常高&#xff08;比如&#xff1a;HLS延迟达到十几秒&#xff0…

Python - 生成可执行文件.exe(附操作完整流程)

文章目录 一、打包工具 - pyinstaller1.1 pyinstaller 原理 二、pyinstaller 安装2.1 管理员身份运行“CMD”-命令提示符2.2 安装2.3 查询是否安装成功 三、pyinstaller 打包可执行文件3.1 进入需要打包的脚本目录3.2 打包脚本3.3 打包结果 四、总结 一、打包工具 - pyinstalle…

Chrome 插件各模块之间的消息传递

Chrome 插件各模块之间的消息传递 一、消息传递 1. 消息传递分类 Chrome 插件的 Action、Background 和 content_script 三个模块之间的信息传输插件和插件之间的信息传输网页向插件进行信息传输与原生应用进行消息传递 2. 消息传递 API runtime API runtime.sendMessage(…

文件操作函数

目录 前言 一、顺序读写函数 1、fgetc 和 fputc 2、fgets 和 fputs 3、fprintf 和 fscanf 4、sscanf 和 sprintf 5、fwrite 和 fread 二、随机读写函数 1、fseek 2、ftell 3、rewind 前言 本章我们学习一下文件操作相关的各种函数 一、顺序读写函数 1、fgetc 和 fpu…

【小黑送书—第十四期】>>重磅升级——《Excel函数与公式应用大全》(文末送书)

今天给大家带来AI时代系列书籍&#xff1a;《Excel 2019函数与公式应用大全》全新升级版&#xff0c;Excel Home多位微软全球MVP专家打造&#xff0c;精选Excel Home海量案例&#xff0c;披露Excel专家多年研究成果&#xff0c;让你分分钟搞定海量数据运算&#xff01; 由北京…

C语言数据结构基础————二叉树学习笔记(四)简单的OJ题目练习

1.单值二叉树 965. 单值二叉树 - 力扣&#xff08;LeetCode&#xff09; 建立一个新的函数&#xff0c;用函数传参的方法来记录val的值 如上一篇最后的对称二叉树的习题&#xff0c;建立新的函数来传参 多采用使用反对值的方法&#xff0c;因为如果是相等return true的话&am…