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;
}

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

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

相关文章

AD9371 官方例程HDL详解之JESD204B TX侧时钟生成 (一)

AD9371 系列快速入口 AD9371ZCU102 移植到 ZCU106 &#xff1a; AD9371 官方例程构建及单音信号收发 ad9371_tx_jesd -->util_ad9371_xcvr接口映射&#xff1a; AD9371 官方例程之 tx_jesd 与 xcvr接口映射 梳理 AD9371 时钟&#xff0c;理解采样率和各个时钟之间的关系 …

linux nginx1.24.0安装

nginx高性能web服务器&#xff0c;可作为一般http应用转发&#xff0c;也可以做mySql、redis、zk、rabbit MQ等tcp数据流转发。 常用Linux服务系统centos和ububtu 只是安装命令不同 yum/apt-get&#xff0c;流程和依赖包是一样的安装方式 1、下载nginx安装包tar.gz官方下载地…

RabbitMQ基础篇 笔记

RabbitMQ 余额支付 同步调用 一步一步的来&#xff0c;支付业务写完后&#xff0c;如果之后加需求&#xff0c;还需要增加代码&#xff0c;不符合开闭原则。 性能上也有问题&#xff0c;openfeign是同步调用&#xff0c;性能太差。 同步调用耦合太多。 同步的优势是可以立…

网站、小程序常见布局样式记录

文章目录 &#x1f380;前言&#xff1a;&#x1f415;网页样式展示小程序&#xff1a;《携程网》&#x1f380;持续更新... &#x1f380;前言&#xff1a; 本篇博客会收藏一些作者见到的网页、小程序页面&#xff0c;目的是用来寻找制作项目网页页面的灵感&#xff0c;有需要…

mysql第一篇---索引

文章目录 mysql第一篇---索引索引的数据结构为什么使用索引&#xff1f;索引的及其优缺点InnoDB中索引的推演常见的索引概念InnoDB的B树索引的注意事项MyISAM中索引方案索引的代价MySQL数据结构选择的合理性 mysql第一篇—索引 索引的数据结构 为什么使用索引&#xff1f; 索…

修炼k8s+flink+hdfs+dlink(六:学习k8s-pod)

一&#xff1a;增&#xff08;创建&#xff09;。 直接进行创建。 kubectl run nginx --imagenginx使用yaml清单方式进行创建。 直接创建方式&#xff0c;并建立pod。 kubectl create deployment my-nginx-deployment --imagenginx:latest 先创建employment&#xff0c;不…

华为OD 高效的任务规划(200分)【java】A卷+B卷

华为OD统一考试A卷+B卷 新题库说明 你收到的链接上面会标注A卷还是B卷。目前大部分收到的都是B卷。 B卷对应20022部分考题以及新出的题目,A卷对应的是新出的题目。 我将持续更新最新题目 获取更多免费题目可前往夸克网盘下载,请点击以下链接进入: 我用夸克网盘分享了「华为O…

紫光展锐携中国联通完成RedCap芯片V517孵化测试

近日&#xff0c;紫光展锐携手中国联通5G物联网OPENLAB开放实验室&#xff08;简称“OPENLAB实验室”&#xff09;共同完成RedCap芯片V517创新孵化&#xff0c;并实现在联通5G全频段3.5GHz、2.1GHz、900MHz下的端到端业务验证测试。 V517是一款基于紫光展锐5G成熟平台设计与研发…

oninput和onchange事件有什么区别以及使用场景

oninput和onchange都是常见的表单元素的事件&#xff0c;它们的区别在于触发的时机不同。 oninput事件会在表单元素的值发生变化时立刻触发&#xff0c;无论是通过键盘输入、粘贴、剪切、拖拽等方式&#xff0c;都能实时响应。比如&#xff1a; <input type"text&quo…

Java反射实体组装SQL

之前在LIS.Core定义了实体特性&#xff0c;在LIS.Model给实体类加了表特性&#xff0c;属性特性&#xff0c;外键特性等。ORM要实现增删改查和查带外键的父表信息就需要解析Model的特性和实体信息组装SQL来供数据库驱动实现增删改查功能。 实现实体得到SQL的工具类&#xff0c…

DOS攻击-ftp_fuzz.py

搭建FTP 使用AlphaFuzzer的FTPFUSS进行攻击 挖掘漏洞&#xff0c;自动用特殊字符看能不能把服务器崩掉 这些都是测试的目录 不能随意使用&#xff0c;可能会把C盘内容清掉 也可以自己写脚本测试下

二叉排序树(BST)

二叉排序树 基本介绍 二叉排序树创建和遍历 class Node:"""创建 Node 节点"""value: int 0left Noneright Nonedef __init__(self, value: int):self.value valuedef add(self, node):"""添加节点node 表示要添加的节点&quo…

使用CMakeLists.txt简化项目构建过程

在软件开发过程中&#xff0c;项目的构建是一个不可避免的环节。而随着项目规模的增大&#xff0c;手动管理编译过程变得越来越繁琐。为了简化构建流程并实现跨平台支持&#xff0c;CMake作为一种流行的构建系统被广泛采用。本文将介绍CMakeLists.txt文件的结构&#xff0c;以及…

读书笔记:Effective C++ 2.0 版,条款28(namespace )

条款28: 划分全局名字空间 namespace 作为前缀&#xff0c;防止不同名字域的类型、常量等互相污染。 没命名的名字空间一般用于限制名字空间内部元素的可见性。 namespace sdm {const double book_version 2.0;class handle { ... };handle& gethandle(); }早期用struct模…

使用序列化技术保存数据 改进 IO流完成项目实战水果库存系统

上一节内容是 使用IO流完成项目实战水果库存系统https://blog.csdn.net/m0_65152767/article/details/133999972?spm1001.2014.3001.5501 package com.csdn.fruit.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java…

springMvc的简介

1.说说你对 SpringMVC 的理解 SpringMVC 是基于对java EE servlet的封装&#xff0c;它是轻量级MVC 框架&#xff0c;它是Spring下的一个模块&#xff0c;我们通过编写一个方法实现对应的handler&#xff0c;一个servlet 请求 2.什么是MVC模式&#xff1f; MVC全名是Model V…

Vue单文件组件

一、.vue文件 我们使用Vue的单文件组件的时候&#xff0c;一个.vue文件就是一个组件。 例如我们创建一个School组件&#xff1a; 二、组件的结构 我们编写网页代码的时候有HTML结构、CSS样式、JS交互。 组件里也是同样存在这三种结构的&#xff1a; <template><d…

System verilog从Testbench中dump出所需要的数据代码

下面是一个System verilog的dump示例代码&#xff1a; define DUMP_PATH $sformatf("./dump/") define CHO_DEINTERLEAVER ldpc_decoder_top_tbch.fec_ofdm_top.fec_ofdm_top_0.de_interleaver initial beginch0_file_ptr_data $fopen($sformatf("%sdump_ch0_…

lodash常用方法合集

安装lodash 建议安装lodash-es&#xff0c;lodash-es 是 lodash 的 es modules 版本 &#xff0c;是着具备 ES6 模块化的版本&#xff0c;体积小。按需引入。 示例 npm i lodash-es import { chunk,compact } from lodash-es; /**按需引入*/ 1.chunk 数组分组 chunk(arra…

redis一主一从搭建

1.复制一份redis.conf并将6380都改成6379 [redist3-dtpoc-dtpoc-web06 conf]$ cp redis.conf redis_6380.conf [redist3-dtpoc-dtpoc-web06 conf]$ vi redis_6380.conf port 6380 daemonize yes pidfile "/home/redis/redis/logs/redis_6380.pid" logfile "/hom…