题目
世界上上最远的距离不是相隔天涯海角
而是我在你面前
可你却不知道我爱你
―― 张小娴
前段日子,枫冰叶子给Wiskey做了个征婚启事,聘礼达到500万哦,天哪,可是天文数字了啊,不知多少MM蜂拥而至,顿时万人空巷,连扫地的大妈都来凑热闹来了。―_―|||
由于人数太多,Wiskey实在忙不过来,就把统计的事情全交给了枫冰叶子,自己跑回家休息去了。这可够枫冰叶子忙的了,他要处理的有两类事情,一是得接受MM的报名,二是要帮Wiskey查找符合要求的MM中缘分最高值。
Input
本题有多个测试数据,第一个数字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)
所有输入的浮点数,均只有一位小数。
Output
对于每一次询问操作,在一行里面输出缘分最高值,保留一位小数。
对查找不到的询问,输出-1。
Sample Input
8
I 160 50.5 60.0
I 165 30.0 80.5
I 166 10.0 50.0
I 170 80.5 77.5
Q 150 166 10.0 60.0
Q 166 177 10.0 50.0
I 166 40.0 99.9
Q 166 177 10.0 50.0
0
Sample Output
80.5
50.0
99.9
解题思路
按照惯例先把线段树模板搬出来,正常来说有两个限制条件需要二维线段树来解决,但是这题有一点特殊。次方法仅这题而言,不作普适解法
读题可知,每个报名者的身高100-200,活跃度0-100,且所有的浮点数只保留一位小数,那我们就可以把身高 * 1000+活跃度 * 10,这样一个人的信息就化成了一串数字,把这个当成一个节点,节点中储存的是缘分度,如果遇到身高和活跃度都完全一样的人就取缘分度最高的一个。这样一操作就化简成一个普通的线段树。查询区间缘分值最高的人时要注意此时应该用一个循环,遍历每一cm身高中要求的缘分度从小到大的区间,取缘分度最高的,这样空间复杂度会比较高,但是时间复杂度还行。比二维线段树慢一点点,在可以接受的范围之内
#include<iostream>
#include<string>
#include"cmath"
#include"cstdio"
#define LL long long
#define MAX 2000010
using namespace std;
double tree[MAX<<2]; // 线段树
//LL lazy[MAX<<2]; // 延迟标记。都要4倍空间
//lazy数组设置的目的:如果我要求的区间覆盖了此子树代表的区间,只需要改子树根节点的lazy值
//就相当于操作这整一个子树,不再需要深入更新
//如果要进行深入某一个节点操作,就把lazy值分配下去(push_down函数),然后递归单独访问要操作的节点
void push_up(int node){//每次操作后,要进行线段树的状态更新
tree[node] = max(tree[node<<1] , tree[node<<1|1]);//根节点保存极大值
//tree[node] = min(tree[node<<1] , tree[node<<1|1]);根节点保存极小值
//tree[node] = tree[node<<1] + tree[node<<1|1];//根节点保存和
}
// 创建线段树
void build(int node,int L,int R){
if(L == R){
scanf("%lld",&tree[node]);
return;
}
int mid = (L+R)>>1;
build(node<<1,L,mid);
build(node<<1|1,mid+1,R);
push_up(node);
}
// 更新,newdata为更新值,indexl/r为要求范围(单点更新indexl==indexr),l,r为更新范围
void update(int indexl,int indexr,double newdata,int L,int R,int node){
if(L==R){
if(newdata*10>tree[node]*10)tree[node]=newdata;
return ;
}
int mid = (L+R) >> 1;
if(indexl<=mid) update(indexl,indexr,newdata,L,mid,node<<1);
if(indexr>mid) update(indexl,indexr,newdata,mid+1,R,node<<1|1);
push_up(node);
}
// 区间查找
double query_range(int node,int L,int R,int indexl,int indexr){
if(indexl <= L && indexr >= R) return tree[node];//满足lazy要求,不用深入操作
int mid = (L+R) >>1;
double ans= 0;
if(mid >= indexl) ans=max(ans,query_range(node<<1,L,mid,indexl,indexr));
if(mid < indexr) ans=max(ans,query_range(node<<1|1,mid+1,R,indexl,indexr));
return ans;
}
int main() {
int n,m;
int case1=0;
while(~scanf("%d",&n)){
int maxn=0,minn=10000000;
if(n==0)break;
for(int i=1;i<=n;i++){
char ch[2];
scanf("%2s",ch);
if(ch[0]=='I'){
int a;double b,c;
scanf("%d%lf%lf",&a,&b,&c);
if(a*1000+b*10>maxn)maxn=a*1000+b*10;
if(a*1000+b*10<minn)minn=a*1000+b*10;
update(a*1000+b*10,a*1000+b*10,c,1,2001000,1);
}else {
int a,b;double c,d;
scanf("%d%d%lf%lf",&a,&b,&c,&d);
if(a>b)swap(a,b);
if(c*10>d*10)swap(c,d);
double anss=0;
for(int i=a;i<=b;i++){
if(query_range(1,1,2001000,i*1000+c*10,i*1000+d*10)>anss)
anss=query_range(1,1,2001000,i*1000+c*10,i*1000+d*10);
}
if(anss!=0)printf("%.1lf\n",anss);
else printf("-1\n");
}
}
}
return 0;
}