「题解」Duck and Dove

二维线段树(线段树套线段树)……

注:此处题目应为“Luck and Love”

一 题目

原题链接

描述

世界上上最远的距离不是相隔天涯海角
而是我在你面前
可你却不知道我爱你 ―― 张小娴

前段日子,枫冰叶子给Wiskey做了个征婚启事,聘礼达到500万哦,天哪,可是天文数字了啊,不知多少MM蜂拥而至,顿时万人空巷,连扫地的大妈都来凑热闹来了。―_―|||
由于人数太多,Wiskey实在忙不过来,就把统计的事情全交给了枫冰叶子,自己跑回家休息去了。这可够枫冰叶子忙的了,他要处理的有两类事情,一是得接受MM的报名,二是要帮Wiskey查找符合要求的MM中缘分最高值。

输入

本题有多个测试数据,第一个数字M,表示接下来有连续的M个操作,当M=0时处理中止。
接下来是一个操作符C。
当操作符为‘I’时,表示有一个MM报名,后面接着一个整数,H表示身高,两个浮点数,A表示活泼度,L表示缘分值。 (100<=H<=200, 0.0<=A,L<=100.0)
当操作符为‘Q’时,后面接着四个浮点数,H1,H2表示身高区间,A1,A2表示活泼度区间,输出符合身高和活泼度要求的MM中的缘分最高值。 (100<=H1,H2<=200, 0.0<=A1,A2<=100.0)
所有输入的浮点数,均只有一位小数。

输出

对于每一次询问操作,在一行里面输出缘分最高值,保留一位小数。
对查找不到的询问,输出-1。


二 题解

二维线段树模板。在一棵线段树的每个节点上,再维护一棵线段树。细节见代码。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;

#define DB double

const int CN = 110;
const DB EPS = 1e-7;

int Q;
/*h的范围是100~200,也就是说这段区间有101个整点*/
/*a的范围是0.0~100.0,先x10,就变成了1001个整点*/
int H = 101,A = 1001; //线段树范围: [1,H] x [1,A]

//(sugment tree)^2
DB d[4*CN][4*CN*10]; //维护节点的值,要开四倍空间
void build(){
for(int i=1;i<=4*H;i++)
for(int j=1;j<=4*A;j++)
d[i][j] = -1; //初始化
}
void sub_modify(int sl,int sr,int sk,int fk,int sa,DB sL){ //第二维修改
if(sl == sr) return (void)(d[fk][sk] = max(d[fk][sk], sL));
int sm = (sl+sr)>>1;
if(sa <= sm) sub_modify(sl,sm,sk<<1,fk,sa,sL);
if(sm < sa) sub_modify(sm+1,sr,sk<<1|1,fk,sa,sL);
d[fk][sk] = max(d[fk][sk<<1], d[fk][sk<<1|1]);
}
void modify(int l,int r,int k,int h,int a,DB L){ //第一维修改
sub_modify(1,A,1,k,a,L); //注意走过的每个节点都要对第二维进行更新
//向下递归
if(l == r) return;
int m = (l+r)>>1;
if(h <= m) modify(l,m,k<<1,h,a,L);
if(m < h) modify(m+1,r,k<<1|1,h,a,L);
}
DB sub_query(int sl,int sr,int sk,int fk,int sas,int sat){ //第二维查询
if(sas<=sl && sr<=sat) return d[fk][sk];
int sm = (sl+sr)>>1;
DB srec = -1;
if(sas <= sm) srec = max(srec, sub_query(sl,sm,sk<<1,fk,sas,sat));
if(sm < sat) srec = max(srec, sub_query(sm+1,sr,sk<<1|1,fk,sas,sat));
return srec;
}
DB query(int l,int r,int k,int hs,int ht,int as,int at){ //第一维查询
if(hs<=l && r<=ht) return sub_query(1,A,1,k,as,at); //确定了第一维中的区间,再去第二维查询
int m = (l+r)>>1;
DB rec = -1;
if(hs <= m) rec = max(rec, query(l,m,k<<1,hs,ht,as,at));
if(m < ht) rec = max(rec, query(m+1,r,k<<1|1,hs,ht,as,at));
return rec;
}

int main()
{
scanf("%d",&Q);
while(Q){
build();
while(Q--){
char c; cin>>c;
if(c == 'I'){
int h; DB a,l;
scanf("%d%lf%lf",&h,&a,&l);
(a *= 10) += 1; h -= 99; //为了让区间端点变成整数
modify(1,H,1,h,(int)a,l);
}
else{
int h1,h2; DB a1,a2;
scanf("%d%d%lf%lf",&h1,&h2,&a1,&a2);
if(h1 > h2) swap(h1,h2); //坑点1
if(a1 > a2) swap(a1,a2);
h1 -= 99; h2 -= 99; (a1 *= 10) += 1; (a2 *= 10) += 1;
DB ans = query(1,H,1,h1,h2,(int)a1,(int)a2);
if(ans < -EPS) printf("-1\n"); //坑点2 输出-1而不是-1.0
else printf("%.1lf\n",ans);
}
}
scanf("%d",&Q);
}

return 0;
}
作者

ce-amtic

发布于

2019-07-17

更新于

2020-12-27

许可协议

CC BY-NC-SA 4.0

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×