写在最前:
这道题,其实最节约时间的算法应该是用FC tree,用该数据结构可以在logn的时间内算出来。
但是,说实话,我写不出这样的树出来,至少目前没必要,因为这样太麻烦了,关键是指针不好指。
所以,我用的是2d range tree。用该数据结构可以在logn^2的时间内算出来!
该数据结构的思想为:
1)先创建AVL树,树的每个节点为站点值
2)将站点按x进行从小到大排序,排序完毕之后,依次插入AVL树的叶子节点中。
并且,站点数组的每个数据留一个指针指向最后的叶子节点,方便后面查找用
同时,还将y数组排序好了给每一个节点!
这一段不看也没事
(这里比较神奇的是,最后插完,刚好只有一个叶子节点的一个右孩子是未被插入的,这个在数学上也是可以解释的,因为叶子的孩子节点数之和刚好比总结点数多1)
解释如下:n个节点,有2n个孩子指针。而2n个孩子指针,需要指向n-1个节点(其中有一个被根节点指了),因此剩余n+1个孩子指针。故再次插入n个节点后,剩余1个指针。而我们插入的顺序是由左至右,即由小到大,故最右边的叶子节点的右孩子指针为空。
3)对于每个X1,X2,Y1,Y2。这里我们对x进行2分查找,找到后即可通过预留的指针找到对应的最末端叶子节点
4)然后顺次走到根节点,只需做的是root=root->parent。
这里需要注意的是,每向上走一步,要留一个指针指向原来的位置,这样我们要是想从交点处回来,也方便!
5)找到x1,x2对应的共同节点,然后共同节点往下走,查找每个节点对应的左子树或者右子树即可!
6)对于每颗右子树或者左子树,他们的x值是不用管的,肯定满足,但是y值是要用二分查找找到的,因此需要花费logn的时间
查找到一个y值,就+它的气温,最后得到总气温了!
如果思路还是看不懂,可以详见https://blog.csdn.net/liuqiyao_01/article/details/8478719
或者看图
最后,附上代码!
#pragma warning(disable:4996)
#include <stdio.h>
#include "temperature.h"
#define maxn 50000
using namespace std;
struct range_node;//范围查询的节点构成范围查询树
//station_type是每一个观测站的具体内容(包括了x,y坐标,温度temp,
//观测站内部还有一个指针c,是用来指向叶子节点,然后用来回溯路径)
//一个指针road,用来指向前一个节点
typedef struct _station_type
{
int x, y;
int temp;
_station_type&operator=(const _station_type&data)
{
temp = data.temp;
x = data.x;
y = data.y;
return *this;
}
range_node*c,*road=NULL;
} station_type;
station_type stations[maxn];
//fctree是用来构建y值数组,每个fctree中都含有station_type类型的data
//y值比较大小,当y值相同时,看x值,这里不可能出现x与y值相同
struct fctree {
station_type data;
bool operator>(const fctree&a)
{
if (data.y > a.data.y)return true;
else if (data.y == a.data.y) {
if (data.x > a.data.x)return true;
else return false;
}
else return false;
}
bool operator<(const fctree&a)
{
if (data.y < a.data.y)return true;
else if (data.y == a.data.y) {
if (data.x < a.data.x)return true;
else return false;
}
else return false;
}
};
//每个节点都有左右指针和对应的y值
//首先要构建AVL树
struct range_node {
range_node*rc, *lc, *parent;
fctree*fc;//这个指针用于指向y数值的数组,记得初始化时要用new fc来确定它的数组大小
int fc_size = 0;
station_type data;//每个节点中都只有一个数据点
int height = 0;
range_node() { rc = lc = NULL; fc = NULL; parent = NULL; }
range_node(const station_type&e, range_node*p,