当前位置: 首页 > news >正文

poj_2352 线段树

题目大意

    对于二维平面上的n个点,给出点的坐标。定义一个点A覆盖的点的个数为满足以下条件的点B的个数:点B的x <= 点A的x坐标,点B的y坐标 <= 点A的y坐标。 
    给出N个点的坐标,求出覆盖点的个数分别为0, 1, ... N-1 的点各有多少个。

题目分析

    对于二维平面的点问题,可以考虑先进行行列排序,然后进行处理。对点进行排序(y从小到大,y相同,x从小到大)之后,按照y从小到大进行:单独考虑一行的点的x坐标,此时x坐标是升序的,因此当前点的肯定可以覆盖当前行中的之前访问的点;对于下方的点,它们的y坐标肯定小于当前点的y坐标,因此只考虑点的x坐标,如果x坐标小于等于当前点的x坐标,则点被当前点覆盖。 
    于是问题就化为了,按照从左下到右上的顺序遍历每个点的时候,比较该点和之前访问过的点的x坐标,如果统计之前点中x坐标小于等于当前点x坐标的个数。也就相当于在x轴上从坐标0到坐标 point.x 这个区间内的点的个数,即一个区间统计问题。 
    区间统计问题,可以采用线段树来进行解决。具体做法是,线段树中的每个节点包含的区间为x坐标轴上的一个范围,遍历到一个点的时候,将点的x坐标插入到线段树中,线段树中的每个节点保存该节点所包含区间内被插入的点的个数。 
这样可以通过两种方式来更新计数: 
1. 从根向下插入点的时候,从根到叶子节点沿途经过的每个点的计数值w都加1 
2. 更新到叶子节点的时候,叶子节点的w值加1,然后通过pushup操作,更新到父节点

实现(c++)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<algorithm>

#define MIN(a, b) a <b? a:b
#define MAX(a, b) a >b? a :b
#define MAX_NUM 32005
#define MAX_NODE 15005
struct Point{
	int x;
	int y;
};
Point gPoints[MAX_NODE];
int gCoverNum[MAX_NODE]; //覆盖i个点的点的数目用 gCoverNum[i]表示
struct TreeNode{
	int beg;
	int end;
	int w;	//表示该节点所代表区间中被插入的点的个数,初始为0,之后每次插入时候,从上往下依次增加
	int Mid(){
		return (beg + end) / 2;
	}
	TreeNode(){
		beg = end = w =  0;
	}
};

TreeNode gTreeNodes[MAX_NUM * 4];

//初始化建树,主要初始化节点的边界和w
void BuildTree(int node, int left, int right){
	gTreeNodes[node].beg = left;
	gTreeNodes[node].end = right;
	gTreeNodes[node].w = 0;
	if (left == right){
		return;
	}
	int mid = (left + right) / 2;
	BuildTree(2*node + 1, left, mid);
	BuildTree(2*node + 2, mid + 1, right);
}

void PushUp(int node){
	gTreeNodes[node].w = (gTreeNodes[2 * node + 1].w + gTreeNodes[node * 2 + 2].w);
}

//向以node为根的树中插入x,沿途中经过的节点的w值均加1
void Insert(int node, int x){
//	gTreeNodes[node].w++;
	if (gTreeNodes[node].beg == gTreeNodes[node].end){
		//不在上面 gTreeNodes[node].w++;,则在这里执行,这样在最后执行 pushup操作。其效果和 开始的时候执行gTreeNodes[node].w++;一样
		gTreeNodes[node].w++;
		return;
	}
	int mid = gTreeNodes[node].Mid();
	if (x > mid){
		Insert(2 * node + 2, x);
	}
	else
		Insert(2 * node + 1, x);

	//如果不使用上面的  	gTreeNodes[node].w++;,则可以使用 PushUp操作,从下往上更新(由于递归的性质,会使得从叶节点到根都会被更新)
	//也就相当于 从上往下插入的时候,每经过一个点都将 w 值加 1
	PushUp(node);  
}

//在以node节点为根的树中查询区间 [s, e]中的元素数目
int Query(int node, int s, int e){
	if (gTreeNodes[node].beg > e || gTreeNodes[node].end < s){
		return 0;
	}
	if (gTreeNodes[node].beg >= s && gTreeNodes[node].end <= e){
		return gTreeNodes[node].w;
	}
	int mid = gTreeNodes[node].Mid();
	int sum = 0;
	sum += Query(2 * node + 1, s, MIN(mid, e));
	sum += Query(2 * node + 2, MAX(s, mid + 1), e);
	return sum;
}
int main(){
	int n;
	scanf("%d", &n);
	int max_end = 0;
	for (int i = 0; i < n; i++){
		scanf("%d%d", &gPoints[i].x, &gPoints[i].y);
		max_end = MAX(max_end, gPoints[i].x);
		gCoverNum[i] = 0;
	}
	BuildTree(0, 0, max_end);
	for (int i = 0; i < n; i++){
		int count = Query(0, 0, gPoints[i].x);
		gCoverNum[count] ++;
		Insert(0, gPoints[i].x);
	}
	for (int i = 0; i < n; i++){
		printf("%d\n", gCoverNum[i]);
	}
	return 0;
}

 

转载于:https://www.cnblogs.com/gtarcoder/p/4717376.html

相关文章:

  • Mac周边环境 goBASIC语言HelloWorld
  • linux内存管理系统后期的内核对zonelist的简化
  • bzoj3809: Gty的二逼妹子序列
  • linux内核page结构体的PG_referenced和PG_active标志
  • 解決BufferedReader读取UTF-8文件中文乱码(转)
  • 问题以及发现问题和解决问题
  • bitmap格式分析(转)
  • 关于数组或集合中判断存在某个元素
  • kexec机制
  • Spring事务配置的五种方式
  • buffer_head和bio
  • 关于人脸识别,稀疏表示的若干论文的小结
  • asp.net——正则表达式
  • 开始iOS 7中自动布局教程(一)
  • POJ 1470 Closest Common Ancestors
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • Cookie 在前端中的实践
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • Laravel 实践之路: 数据库迁移与数据填充
  • linux学习笔记
  • MySQL QA
  • mysql 数据库四种事务隔离级别
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • vue学习系列(二)vue-cli
  • 第2章 网络文档
  • 动态规划入门(以爬楼梯为例)
  • 关于Java中分层中遇到的一些问题
  • 机器学习 vs. 深度学习
  • 基于Android乐音识别(2)
  • 我建了一个叫Hello World的项目
  • 小程序01:wepy框架整合iview webapp UI
  • 终端用户监控:真实用户监控还是模拟监控?
  • 带你开发类似Pokemon Go的AR游戏
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • #git 撤消对文件的更改
  • #HarmonyOS:基础语法
  • #pragma data_seg 共享数据区(转)
  • #QT(一种朴素的计算器实现方法)
  • $.ajax()方法详解
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (二)WCF的Binding模型
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (实战篇)如何缓存数据
  • (一)80c52学习之旅-起始篇
  • (转)项目管理杂谈-我所期望的新人
  • 、写入Shellcode到注册表上线
  • .form文件_SSM框架文件上传篇
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料