Luck and Love题解(非二维数组,取巧解法)

这篇博客介绍了一种非二维数组的解题策略,通过将身高和活泼度转化为一个数字,利用线段树解决寻找指定身高和活泼度范围内缘分值最高的MM的问题。在处理大量数据时,虽然时间复杂度略高,但避免了二维线段树的使用。
摘要由CSDN通过智能技术生成

题目

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

前段日子,枫冰叶子给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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值