POJ 3470 Walls 树上分桶
今天太晚了,代码先发上,思路明天说吧。
陌上花开,树上分桶
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
/*** 对于y1不等于y2的,可以用datC求解,对于x1不等于x2的,可以用datR求解* 因此需要结合datC和y1==y2的same,结合datR和x1==x2的same,才能求解问题*/
struct Same
{//_same是墙相等的那一个坐标,例如x1=x2,_other是墙不相等的那一个坐标,例如y1,_idx是墙的下标int _same, _other, _idx;Same(int _same = 0, int _other = 0, int _idx = 0) : _same(_same), _other(_other), _idx(_idx) {}
};
bool compareSame(const Same &a, const Same &b)
{// 如果相等元素相同,则按照相同元素排if (a._same != b._same){return a._same < b._same;}// 如果相同元素不同,则按照不同元素排else{return a._other < b._other;}
}
/*** sameX记录了x1==x2的墙,优先按照x1排序,其次按照y1排序,sameY记录了y1==y2的墙,优先按照y1排序,其次按照x1排序*/
Same sameX[50009], sameY[50009];
/*** sameX和sameY里元素的数量*/
int sameXLen, sameYLen;
typedef pair<int, int> P;
/*** 树上分桶的大小*/
const int B = 1500;
/*** x1不等于x2的墙,即水平方向,用R(row)表示,这个数组保存的是x2,用于统计x1<=x<=x2的个数*/
P **datR;
/*** y1不等于y2的墙,即竖直方向,用C(col)表示,这个数组保存的是y2,用于统计y1<=y<=y2的个数*/
P **datC;
/*** bktR[i]是对datR[i]的分桶*/
P ***bktR;
int **bktRSize;
/*** bktC[i]是对datC[i]的分桶*/
P ***bktC;
int **bktCSize;
/*** 输入*/
int x1[50009], x2[50009], y1[50009], y2[50009], x[50009], y[50009], n, m;
/*** 把x1!=x2的墙都放在row里保存,并按照x1排序,把y1!=y2的墙度放在col里保存,并按照y1排序*/
P row[50009], col[50009];
/*** rowLen是row数组里元素的数量,colLen是col数组里元素的数量*/
int rowLen, colLen, bktRLen[131072], bktCLen[131072];
/***因为我们把x1!=x2和y1!=y2的墙分到了两颗树,所以用一个变量代表当前查询哪一颗树,如果isR==true,则查的datR,否则datl*/
bool isR;
/***让x1<=x2,y1<=y2*/
void swapIfNeed(int i)
{int tmp;if (y1[i] > y2[i]){tmp = y1[i];y1[i] = y2[i];y2[i] = tmp;}if (x1[i] > x2[i]){tmp = x1[i];x1[i] = x2[i];x2[i] = tmp;}
}
void input()
{scanf("%d%d", &n, &m);rowLen = 0, colLen = 0, sameXLen = 0, sameYLen = 0;for (int i = 0; i < n; i++){scanf("%d%d%d%d", &x1[i], &y1[i], &x2[i], &y2[i]);swapIfNeed(i);if (x1[i] != x2[i]){row[rowLen].first = x1[i];row[rowLen].second = i;rowLen++;}if (y1[i] != y2[i]){col[colLen].first = y1[i];col[colLen].second = i;colLen++;}if (x1[i] == x2[i]){sameX[sameXLen]._same = x1[i];sameX[sameXLen]._other = y1[i];sameX[sameXLen]._idx = i;sameXLen++;}if (y1[i] == y2[i]){sameY[sameYLen]._same = y1[i];sameY[sameYLen]._other = x1[i];sameY[sameYLen]._idx = i;sameYLen++;}}for (int i = 0; i < m; i++){scanf("%d%d", &x[i], &y[i]);}
}
void sortAll()
{sort(sameX, sameX + sameXLen, compareSame);sort(sameY, sameY + sameYLen, compareSame);sort(row, row + rowLen);sort(col, col + colLen);
}
void buildBkt(int i, int size)
{int len = size / B;if (size % B != 0){len++;}if (isR){bktR[i] = new P *[len];bktRSize[i] = new int[len];bktRLen[i] = len;}else{bktC[i] = new P *[len];bktCSize[i] = new int[len];bktCLen[i] = len;}for (int j = 0; j < len; j++){if (j + 1 == len){if (isR){bktR[i][j] = new P[size - (B * j)];bktRSize[i][j] = size - (B * j);}else{bktC[i][j] = new P[size - (B * j)];bktCSize[i][j] = size - (B * j);}}else{if (isR){bktR[i][j] = new P[B];bktRSize[i][j] = B;}else{bktC[i][j] = new P[B];bktCSize[i][j] = B;}}}for (int j = 0; j < size; j++){if (isR){bktR[i][j / B][j - ((j / B) * B)].first = y1[datR[i][j].second];bktR[i][j / B][j - ((j / B) * B)].second = datR[i][j].second;}else{bktC[i][j / B][j - ((j / B) * B)].first = x1[datC[i][j].second];bktC[i][j / B][j - ((j / B) * B)].second = datC[i][j].second;}}for (int j = 0; j < len; j++){if (isR){sort(bktR[i][j], bktR[i][j] + bktRSize[i][j]);}else{sort(bktC[i][j], bktC[i][j] + bktCSize[i][j]);}}
}
/*** 构建线段树*/
void buildDat(int i, int l, int r)
{if (r - l == 1){// 如果目前是操作的datRif (isR){datR[i] = new P[1];datR[i][0].first = x2[row[l].second];datR[i][0].second = row[l].second;}else{datC[i] = new P[1];datC[i][0].first = y2[col[l].second];datC[i][0].second = col[l].second;}}else{int lch = i * 2 + 1;int rch = i * 2 + 2;int mid = (l + r) / 2;buildDat(lch, l, mid);buildDat(rch, mid, r);if (isR){datR[i] = new P[r - l];merge(datR[lch], datR[lch] + (mid - l), datR[rch], datR[rch] + (r - mid), datR[i]);}else{datC[i] = new P[r - l];merge(datC[lch], datC[lch] + (mid - l), datC[rch], datC[rch] + (r - mid), datC[i]);}}buildBkt(i, r - l);
}
/*** ans数组用来存放第i面墙被撞的次数,ansIdx[i]用来存放第i只小鸟撞到的墙,ansLen用来存放第i只小鸟撞到的墙的数量,ansDist存放第i只小鸟距墙的最近距离*/
int ans[50009], ansIdx[50009][10], ansLen[500009], ansDist[50009];
/*** _x,_y代表当前小鸟的位置,_current代表它的下标*/
int _x, _y, _current;
void updateAns(int dist, int idx)
{if (ansDist[_current] == 0 || ansDist[_current] == dist){ansIdx[_current][ansLen[_current]] = idx;ansLen[_current] = ansLen[_current] + 1;ansDist[_current] = dist;}else if (ansDist[_current] > dist){ansLen[_current] = 0;ansIdx[_current][ansLen[_current]] = idx;ansLen[_current] = ansLen[_current] + 1;ansDist[_current] = dist;}
}
void handleNode(int i, int l, int r)
{int size = r - l;P tmp;int idx, dist, bktSize;if (isR){tmp = P(_x, -0x3f3f3f3f);idx = lower_bound(datR[i], datR[i] + size, tmp) - datR[i];bktSize = bktRLen[i];}else{tmp = P(_y, -0x3f3f3f3f);idx = lower_bound(datC[i], datC[i] + size, tmp) - datC[i];bktSize = bktCLen[i];}if (idx >= size){return;}int firstBkt = (idx + B - 1) / B;for (int j = idx; j < min(size, firstBkt * B); j++){if (isR){dist = abs(y1[datR[i][j].second] - _y);updateAns(dist, datR[i][j].second);}else{dist = abs(x1[datC[i][j].second] - _x);updateAns(dist, datC[i][j].second);}}for (int j = firstBkt; j < bktSize; j++){if (isR){tmp.first = _y;idx = lower_bound(bktR[i][j], bktR[i][j] + bktRSize[i][j], tmp) - bktR[i][j];if (idx < bktRSize[i][j]){dist = abs(bktR[i][j][idx].first - _y);updateAns(dist, bktR[i][j][idx].second);}idx--;if (idx >= 0){dist = abs(bktR[i][j][idx].first - _y);updateAns(dist, bktR[i][j][idx].second);}}else{tmp.first = _x;idx = lower_bound(bktC[i][j], bktC[i][j] + bktCSize[i][j], tmp) - bktC[i][j];if (idx < bktCSize[i][j]){dist = abs(bktC[i][j][idx].first - _x);updateAns(dist, bktC[i][j][idx].second);}idx--;if (idx >= 0){dist = abs(bktC[i][j][idx].first - _x);updateAns(dist, bktC[i][j][idx].second);}}}
}
void query(int _l, int _r, int i, int l, int r)
{if (_l >= r || _r <= l){}else if (l >= _l && r <= _r){handleNode(i, l, r);}else{query(_l, _r, i * 2 + 1, l, (l + r) / 2);query(_l, _r, i * 2 + 2, (l + r) / 2, r);}
}
void solveSame()
{int idx, dist;Same tmp;if (isR){tmp = Same(_x, _y, -0x3f3f3f3f);idx = lower_bound(sameX, sameX + sameXLen, tmp, compareSame) - sameX;if (idx < sameXLen && sameX[idx]._same == _x){dist = sameX[idx]._other - _y;updateAns(dist, sameX[idx]._idx);}idx--;if (idx >= 0 && sameX[idx]._same == _x){dist = _y - y2[sameX[idx]._idx];updateAns(dist, sameX[idx]._idx);}}else{tmp = Same(_y, _x, -0x3f3f3f3f);idx = lower_bound(sameY, sameY + sameYLen, tmp, compareSame) - sameY;if (idx < sameYLen && sameY[idx]._same == _y){dist = sameY[idx]._other - _x;updateAns(dist, sameY[idx]._idx);}idx--;if (idx >= 0 && sameY[idx]._same == _y){dist = _x - x2[sameY[idx]._idx];updateAns(dist, sameY[idx]._idx);}}
}
void solve(int i)
{_x = x[i], _y = y[i], _current = i;solveSame();int idx;P tmp;if (isR && rowLen > 0){tmp = P(_x, 0x3f3f3f3f);idx = upper_bound(row, row + rowLen, tmp) - row;if (idx <= 0){return;}query(0, idx, 0, 0, rowLen);}else if (colLen > 0){tmp = P(_y, 0x3f3f3f3f);idx = upper_bound(col, col + colLen, tmp) - col;if (idx <= 0){return;}query(0, idx, 0, 0, colLen);}
}
void putAns()
{for (int i = 0; i < m; i++){for (int j = 0; j < ansLen[i]; j++){ans[ansIdx[i][j]]++;}}for (int i = 0; i < n; i++){printf("%d\n", ans[i]);}
}
int calcSize(int _size)
{int size = 1;while (size < _size){size = size * 2;}return size * 2 - 1;
}
int main()
{input();sortAll();isR = true;if (rowLen > 0){datR = new P *[calcSize(rowLen)];bktR = new P **[calcSize(rowLen)];bktRSize = new int *[calcSize(rowLen)];buildDat(0, 0, rowLen);}isR = false;if (colLen > 0){datC = new P *[calcSize(colLen)];bktC = new P **[calcSize(colLen)];bktCSize = new int *[calcSize(colLen)];buildDat(0, 0, colLen);}for (int i = 0; i < m; i++){isR = true;solve(i);isR = false;solve(i);}putAns();return 0;
}
相关文章:
POJ 3470 Walls 树上分桶
今天太晚了,代码先发上,思路明天说吧。 陌上花开,树上分桶 #include <iostream> #include <algorithm> #include <vector> using namespace std; /*** 对于y1不等于y2的,可以用datC求解,对于x1不等…...
HIVE-17824,删除hdfs分区信息,清理metastore元数据
当手动删除HDFS 分区数据时,但是并没有清理 Hive 中的分区元数据,删除操作无法自动更新hive分区表元数据。也就是从hdfs中删除大量分区数据,并没有执行如下命令: alter table drop partition commad 从hive 3.0.0开始可以使用MSCK的方法发现新分区或删除丢失的分区; MSCK [REPA…...
Python深度学习进阶与应用丨注意力(Attention)机制、Transformer模型、生成式模型、目标检测算法、图神经网络、强化学习详解等
目录 第一章 注意力(Attention)机制详解 第二章 Transformer模型详解 第三章 生成式模型详解 第四章 目标检测算法详解 第五章 图神经网络详解 第六章 强化学习详解 第七章 深度学习模型可解释性与可视化方法详解 更多应用 近年来,伴…...

javaEE -6(10000详解文件操作)
一:认识文件 我们先来认识狭义上的文件(file)。针对硬盘这种持久化存储的I/O设备,当我们想要进行数据保存时,往往不是保存成一个整体,而是独立成一个个的单位进行保存,这个独立的单位就被抽象成文件的概念,…...

图像处理之《基于多MSB预测和Huffman编码的加密图像可逆数据隐藏》论文精读
一、文章摘要 随着云存储和隐私保护的发展,可逆数据隐藏在加密图像中(RDHEI)作为一种技术越来越受到人们的关注,它可以:在图像加密领域嵌入额外的数据,确保嵌入的数据可以无差错地提取,原始图像可以无损地恢复。本文提…...

Nginx安装配置项目部署然后加SSL
个人操作笔记记录 第一步:把 nginx 的源码包nginx-1.8.0.tar.gz上传到 linux 系统 第二步:解压缩 tar zxvf nginx-1.8.0.tar.gz 第三步:进入nginx-1.8.0目录 使用 configure 命令创建一 makeFile 文件。 直接复制过去运行 ./configur…...

【算法练习Day26】分发饼干摆动序列 最大子数组和
📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:练题 🎯长路漫漫浩浩,万事皆有期待 文章目录 分发饼干摆动序列最大子数组…...
redis缓存击穿/穿透/雪崩面试回答
面试官:什么是缓存穿透 ? 怎么解决 ? 候选人: 嗯~~,我想一下 缓存穿透是指查询一个一定不存在的数据,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到 DB 去查询,可能导致…...

Jmeter性能测试 —— TPS拐点寻找
寻找TPS性能拐点1、准备脚本①在本地电脑调试Jmeter压测脚本 ②上传到压测机Jmeter所在的服务器 2、执行压力测试①执行压测脚本 jmeter –n –t xianchengzuse.jmx ②记录业务压测数据 3、监控服务器性能指标 ①监控CPU输入top命令 ②监控内存 free –m ③jstat监控sweep和…...

科技资讯|苹果穿戴新专利,表带、服装等织物可变身柔性屏幕或扬声器
根据美国商标和专利局(USPTO)本周公示的清单,苹果公司获得了一项新的技术专利,可以在 Apple Watch 表带、服装等物品上,引入基于织物的柔性扬声器。 根据专利描述,通过在织物中嵌入声学组件(例…...

数据分析和机器学习的11个高级可视化图表介绍
可视化是一种强大的工具,用于以直观和可理解的方式传达复杂的数据模式和关系。它们在数据分析中发挥着至关重要的作用,提供了通常难以从原始数据或传统数字表示中辨别出来的见解。 可视化对于理解复杂的数据模式和关系至关重要,我们将介绍11…...

祝所有的程序猿们2023年的1024节快乐~
许久没更新Bolg了,眼看就要到1024节,其实也是没有可以更新的东西,目前在PhD,发现很多东西都还需要慢慢沉淀,放一doctoral college 开学的时候ppt的老图。 越往深处研究会陷入泥潭,考虑的细节将会越来越多&…...

Win10/Win11系统bitlocker正在等待激活如何解决?
有同学升级Win10系统后,发现C盘与D盘分区盘符中出现了黄色的锁定感叹号,还显示“bitlocker正在等待激活”,这可能是用户开启了bitlocker加密所导致的。下面就来看看解决的办法吧。 一、bitlocker正在等待激活的解决方法 打开控制面板-系统和安…...

酷开科技 | 酷开系统,为居家生活打开更精彩的窗口
电视在我们的日常生活中扮演着重要的角色。虽然,作为客厅C位的扛把子——电视的娱乐作用深入人心,但是,它的涵义和影响力却因我们每个人的具体生活环境而存在着种种差异,而我们的生活环境又受到我们所处的社会及文化环境的影响。 …...

谷歌真的不喜欢 Node.js ?
有人在 Quora 上提问,为什么谷歌不喜欢 Node.js 呢,Google 的 UX 工程师和来自 Node.js 团队的开发者分别回答了他们对这个问题的看法,对于编程语言来说,每一门语言都有它自己的优势,重要的是如何用它去解决问题。 谷…...
前端项目如何找到所有未被引用的文件
要找到 React 项目中所有未被引用的文件,可以使用工具来进行静态代码分析。以下是一些方法: 使用静态代码分析工具unimported: 静态代码分析工具可以找到未被引用的 JSX 文件。一个常用的工具是 “unimported”。以下是使用它的步骤ÿ…...

CANoe-使用IG Ethernet Packet Builder实现IP包分片的若干问题
在文章《CANoe-Ethernet IG和Ethernet Packet Builder的使用和区别》中,我们讲过Packet Builder可以组装多种类型的以太网报文: 当我们想组装一条icmpv4 echo request报文,payload只有1个字节的数据FF时,选择ICMPv4 Packet,创建一条ICMPv4报文,把payload改为1个字节: 然…...

UE4逆向篇-2_各类数据的查找方式
写在前面 1.通过前面的文章,相信各位已经能够自己找到GNames并使用DUMP工具导出GNames了。 2.本篇文章将介绍各种所需数据的查找方法。 一、准备工作 1.CheatEngine,本篇以及后续篇幅的重要工具。 2.一个记事本,保证你能记录下关键信息。…...
JDBC-day07(Apache-DBUtils实现CRUD操作)
九:Apache-DBUtils实现CRUD操作 1 Apache-DBUtils简介 Apache-DbUtils 是 Apache 组织提供的开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用DbUtils能极大简化JDBC编码的工作量,同时也不会影响程序的…...

零代码编程:用ChatGPT多线程批量将PDF文档转换为word格式
pdf2docx是Python的一个库,可以很方便的将PDF文档转换为word格式,首先安装这个库。 然后在ChatGPT中输入提示词: 你是一个Python编程专家,要完成一个文档格式转换的任务,具体步骤如下: 打开F盘的Books文件…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...