小w征婚问题
问题描述
小w征婚,收到很多女生报名,小w想找出其中符合要求的最有缘分的人。
输入
- 第一行输入一个整数
t
,代表有t
个操作。 - 之后的
t
行每行输入一种操作:- 操作“I”,表示一个女生报名,输入女生的三个信息:身高
H
(整数),活泼度A
(浮点数),缘分L
(浮点数)。 - 操作“Q”,表示一个查询操作,输入四个浮点数:
H1,H2
表示身高区间,A1,A2
表示活泼度区间。
- 操作“I”,表示一个女生报名,输入女生的三个信息:身高
输出
- 对于每次查询操作,输出符合身高和活泼度区间中的缘分最大值。若没有符合条件的女生,则输出-1。
区间范围
100.0 <= H1, H2 <= 200.0
0 <= A1, A2, L <= 100.0
示例
输入示例
5
I 165 30.5 55.0
I 170 25.0 70.0
Q 160.0 180.0 20.0 40.0
I 168 35.0 85.0
Q 165.0 175.0 25.0 35.0
输出示例
-1
85.0
解释:
- 第一次查询,没有女生的身高在
[160.0, 180.0]
且活泼度在[20.0, 40.0]
之间,所以输出-1。 - 第二次查询,有一个女生的身高在
[165.0, 175.0]
且活泼度在[25.0, 35.0]
之间(即新加入的女生),她的缘分值是85.0,所以输出85.0。
#include<iostream>
#include<algorithm>
using namespace std;
int ls(int p) { return p << 1; }
int rs(int p) { return p << 1 | 1; }
int n = 1000, s[1005][4005]; //s[i][j],表述身高区间i,活泼区间j中的最大缘分,注意这书二维线段树,所以i,j都代表以[ls(i/j),rs(i/j)]为区间的线段树节点,(线段树中除了叶子节点其余节点都为区间)
//建立二维线段树
void subbuild(int xp, int p, int pl, int pr) {
//xp代表身高区间,p代表活泼度区间
s[xp][p] = -1; //初始化为一个最小数
if (pl == pr) return;
int mid = (pl + pr) >> 1; //递归到叶子节点
//只更新一棵树上的节点,其实二维数组中有很多空间被浪费,这是树结构的特性所致
subbuild(xp, ls(p), pl, mid);
subbuild(xp, rs(p), mid + 1, pr);
}
void build(int p, int pl, int pr) {
subbuild(p, 1, 0, n);
if (pl == pr) return;
int mid = (pl + pr) >> 1;
build(ls(p), pl, mid);
build(rs(p), mid + 1, pr);
}
void subupdate(int xp, int y, int c, int p, int pl, int pr) {
if (pl == pr && pl == y) s[xp][p] = max(s[xp][p], c); //到达叶子节点
else {
int mid = (pl + pr) >> 1;
if (y <= mid) subupdate(xp, y, c, ls(p), pl, mid);
else subupdate(xp, y, c, rs(p),mid + 1, pr);
s[xp][p] = max(s[xp][ls(p)], s[xp][rs(p)]); //线段树的pushup函数,需要更新所有区间
}
}
void update(int x, int y, int c, int p, int pl, int pr) {
subupdate(p, y, c, 1, 0, n);
if (pl != pr) {
int mid = (pl + pr) >> 1;
if (x <= mid) update(x, y, c, ls(p), pl, mid);
else update(x, y, c, rs(p), mid + 1, pr);
}
}
int subquery(int xp, int yl, int yr, int p, int pl, int pr) {
if (yl <= pl && pr <= yr) return s[xp][p]; //搜索到了符合活泼度的区间
else {
int mid = (pl + pr) >> 1;
int res = -1;
if (yl <= mid) res = subquery(xp, yl, yr, ls(p), pl, mid);
if (yr > mid) res = max(res, subquery(xp, yl, yr, rs(p), mid + 1, pr));
return res;
}
}
int query(int xl, int xr, int yl, int yr, int p, int pl, int pr) {
if (xl <= pl && pr >= xr) return subquery(p, yl, yr, 1, 0, n); //搜索到了符合身高的区间
else {
int mid = (pl + pr) >> 1;
int res = -1;
if (xl <= mid) res = query(xl, xr, yl, yr, ls(p), pl, mid);
else res = max(res, query(xl, xr, yl, yr, rs(p), mid + 1, pr));
return res;
}
}
int main() {
int t;
while (scanf("%d", &t) && t) {
build(1, 100, 200);
while (t--) {
char ch[2]; scanf("%s", ch);
if (ch[0] == 'I') {
int h; double c, d; cin >> h >> c >> d;
update(h, c * 10, d * 10, 1, 100, 200); //c和d为浮点数需要凑整,否则无法使用"<<"移位符号
}
else {
int xl, xr, yl, yr; double c, d;
cin >> xl >> xr >> c >> d;
yl = c * 10; yr = d * 10; //活泼度区间也为浮点数也需要转化为整数,原因同上
//防止大小颠倒
if (xl > xr) swap(xl, xr);
if (yl > yr) swap(yl, yr);
int ans = query(xl, xr, yl, yr, 1, 100, 200); //[100,200]为身高区间
if (ans == -1) cout << ans;
else cout << ans / 10.0;
}
}
}
return 0;
}