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

【题目描述】

有一根围绕原点 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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

服务运营 | 印第安纳大学翟成成:改变生活的水井选址

编者按&#xff1a; 作者于2023年4月在“Production and Operations Management”上发表的“Improving drinking water access and equity in rural Sub-Saharan Africa”探讨了欠发达地区水资源供应中的可达性和公平性问题。作者于2020年1月去往非洲埃塞俄比亚提格雷地区进行…

鸿蒙操作系统-初识

HarmonyOS-初识 简述安装配置hello world1.创建项目2.目录解释3.构建页面4.真机运行 应用程序包共享包HARHSP 快速修复包 官方文档请参考&#xff1a;HarmonyOS 简述 1.定义&#xff1a;HarmonyOS是分布式操作系统&#xff0c;它旨在为不同类型的智能设备提供统一的操作系统&a…

【前端学习——js篇】4.浅拷贝与深拷贝

具体可见https://github.com/febobo/web-interview 4.浅拷贝与深拷贝 ①栈内存与堆内存 栈内存&#xff08;Stack Memory&#xff09; 栈内存用于存储基本类型的变量和引用类型的变量引用&#xff08;即指向堆内存中实际数据的指针&#xff09;。当一个函数被调用时&#xf…

javaWeb医院在线挂号系统

功能描述 医院挂号系统主要用于实现医院的挂号&#xff0c;前台基本功能包括&#xff1a;用户注册、用户登录、医院查询、挂号、取消挂号、修改个人信息、退出等。 后台基本功能包括&#xff1a;系统管理员登录、医院管理、科室管理、公告管理、退出系统等。 本系统结构如下&…

申请IP地址证书

目录 IP证书的验证条件&#xff1a; 为什么需要申请IP地址证书&#xff1f; 申请IP证书的方法&#xff1a; 注释&#xff1a;IP地址证书也是SSL证书的一种&#xff0c;在验证IP地址所有权后部署于服务器上可实现https访问的一种证书。用公网IP证书可以解决很多问题&#xff…

JavaWeb学习笔记01

一、教程简介 全新JAVAWEB&#xff08;里程碑版&#xff09; 一套更适合后端工程师学习的WEB教程 All in Java 1、后端 ① Spring全家桶及微服务框架 ② 高性能数据库和消息组件 ③ Web攻击防护安全控制手段 ④ 其他第三方SDK生态环境 ...... 2、前端 ① 视图三大件&…

构建医疗服务新平台:开发智慧医院系统源码实战教学

本篇文章&#xff0c;小编将深入探讨如何通过开发智慧医院系统源码&#xff0c;构建医疗服务新平台的实战教学。 一、开发准备 在开始开发智慧医院系统之前&#xff0c;我们首先需要明确系统的功能需求和技术实现方案。 二、实战教学 1.系统架构设计 这包括数据库设计、前后…

【Git】日志功能

1. git日志显示 # 显示前3条日志 git log -3# 单行显示 git log --oneline# 图表日志 git log --graph# 显示更改摘要 git log --stat# 显示更改位置 git log --patch 或 git log -p# 查看指定文件的提交历史记录 git log {filename}例子1&#xff1a;单行显示 例子2&#xff…

洛谷_P4995 跳跳!_python写法

P4995 跳跳&#xff01; - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) n int(input()) data list(map(int,input().split())) data.append(0) data.sort()sum 0 l 0 r len(data)-1 flag 1 while l<r:sum (data[l]-data[r])**2if flag:l 1flag 0else:r - 1flag 1…

Wind X98 DM R2蓝牙5.2双模热插拔PCB

键盘使用说明索引&#xff08;均为出厂默认值&#xff09; 一些常见问题解答&#xff08;FAQ&#xff09;注意首次使用步骤蓝牙配对&#xff08;重要&#xff09;蓝牙和USB切换键盘默认层默认触发层0的FN键配置的功能默认功能层1配置的功能默认的快捷键 蓝牙参数蓝牙MAC地址管理…

发现了一本超厉害的英语秘籍,绝对YYDS

昨天冷月小姐姐分享了一本书&#xff0c;她说是一位英语大神发她的。 我也打开了&#xff0c;很酷炫。 群友们也在与时俱进&#xff0c;随手截图&#xff0c;分享了大模型对文档的理解。 你可能会想&#xff0c;关注宏观经济有啥用&#xff0c;自己只是大海中的浪花一朵。 还有…

相交链表:寻找链表的公共节点

目录 一、公共节点 二、题目 三、思路 四、代码 五、代码解析 1.计算长度 2.等长处理 3.判断 六、注意点 1.leetcode的尿性 2.仔细观察样例 3.经验总结 一、公共节点 链表不会像两直线相交一样&#xff0c;相交之后再分开。 由于单链表只有一个next指针&#xff0…

github配置ssh

生成公钥 在电脑用户的目录下打开终端执行 ssh-keygen -t rsa: 执行完不要关 配置文件 看看用户的目录里 .ssh 目录&#xff1a; Host github.comHostname ssh.github.comPort 443配置公钥 复制 id_rsa.pub 文件里的内容 粘贴到 github上 连接密钥 回到刚才的终端…

Windows系统部署Net2FTP网站结合内网穿透轻松打造可公网访问个人云盘

文章目录 1.前言2. Net2FTP网站搭建2.1. Net2FTP下载和安装2.2. Net2FTP网页测试 3. cpolar内网穿透3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 文件传输可以说是互联网最主要的应用之一&#xff0c;特别是智能设备的大面积使用&#xff0c;无论是个人…

【主成分分析(PCA)】

文章目录 一、什么是主成分分析&#xff08;PCA&#xff09;&#xff1f;主成分的选取方差的重要性数据降维 PCA的应用场景 二、主成分分析的工作原理1.方差和数据的重要性2.计算协方差矩阵3.特征值和特征向量4.选择主成分 三、PCA的实现步骤1.标准化数据集2.计算协方差矩阵3.计…

Windows应用商店打不开怎么办?

大家习惯在windows应用商店下载应用和软件,操作也很方便。最近,有用户却称,win10系统上网情况一切正常,但是就是无法打开应用商店,同时还伴随闪退。这该怎么办呢?针对此故障,小编整理好了解决方法,接下来,将和大家分享Windows应用商店打不开怎么办。 操作方法如下: 1…

SpringBoot如何优雅的进行参数校验

一、传统参数校验 虽然往事不堪回首&#xff0c;但还是得回忆一下我们传统参数校验的痛点。 下面是我们传统校验用户名和邮箱是否合法的代码 if (username null || username.isEmpty()) {throw new IllegalArgumentException("用户名不能为空"); }if (isValidEmai…

如何使用PHP和RabbitMQ实现延迟队列(方式一)?

前言 今天我们来做个小试验&#xff0c;用PHP和RabbitMQ实现消息队列的延迟功能。 前期准备&#xff0c;需要安装好docker、docker-compose的运行环境。 需要安装RabbitMQ的可以看下面这篇文章。 如何使用PHP和RabbitMQ实现消息队列&#xff1f;-CSDN博客 一、安装RabbitM…

抖音视频关键词批量采集工具|无水印视频爬虫提取软件

抖音视频关键词批量采集工具&#xff1a; 我们很高兴地介绍最新推出的抖音视频关键词批量采集工具&#xff0c;该工具集成了多项强大功能&#xff0c;让您轻松实现视频内容的批量提取和下载。以下是详细的功能解析和操作说明&#xff1a; 主要功能&#xff1a; 关键词批量提取…

【GIS前沿技术】推荐几款高大上的在线地图,地理学者的福音!

文章目录 一、https://zoom.earth/二、https://www.ventusky.com/三、https://earth.nullschool.net四、https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer?fjsapi 一、https://zoom.earth/ 卫星&#xff1a; 雷达&#xff1a; 降水&#xff…