HDU1823(线段树)

本文详细介绍了如何利用二维线段树解决HDU1823题目,涉及动态规划和ACM竞赛策略。通过C++实现,探讨了算法在处理二维区间查询和更新上的效率和实用性。
摘要由CSDN通过智能技术生成

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

前段日子,枫冰叶子给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
 

      第一道二维线段树的题,模仿着模板写下的。

#include<iostream>
#include<cstdio>

using namespace std;

float meili[5005][5005<<2];			// 这里二维表示身高和活力,结果是缘分
int N;
double max(double a, double b)
{
	return a>b ? a : b;
}
void build2(int l, int r, int deep, int rt) //在活力方向上初始化。
{
	meili[deep][rt] = -1.0;
	if (l == r)
		return;
	int mid = (l + r) >> 1;
	build2(l, mid, deep, rt << 1);
	build2(mid + 1, r, deep, rt << 1 | 1);
}
void build(int l, int r, int root)  //在每一高度上,转移给活力进行初始化
{
	build2(0, 1000, root, 1);
	if (l == r)
		return;
	int mid = (l + r) >> 1;
	build(l, mid, root << 1);
	build(mid + 1, r, root << 1 | 1);
}
void I2(int act, float love, int l, int r, int deep, int rt)    //对插入量进行活力上的定位,并对相关量更新
{
	meili[deep][rt] = max(love, meili[deep][rt]);      //对根进行更新
	if (l == r)
		return;
	int mid = (l + r) >> 1;
	if (mid >= act)
		I2(act, love, l, mid, deep, rt << 1);
	else
		I2(act, love, mid + 1, r, deep, rt << 1 | 1);
	meili[deep][rt] = max(meili[deep][rt << 1], meili[deep][rt << 1 | 1]); //对根进行更新
}
void I(int h, int act, float love, int l, int r, int rt)     //对插入量进行一次高度上的定位
{
	I2(act, love, 0, 1000, rt, 1);
	if (l == r)
		return;
	int mid = (l + r) >> 1;
	if (mid >= h)
		I(h, act, love, l, mid, rt << 1);
	else
		I(h, act, love, mid + 1, r, rt << 1 | 1);
}
float Q2(int act1, int act2, int l, int r, int deep, int rt)   //要求【act1,act2】范围,目前以rt为根是【l,r】范围
{
	if (act1 <= l&&r <= act2)
		return meili[deep][rt];
	int mid = (l + r) >> 1;
	if (mid >= act2)
		return Q2(act1, act2, l,mid, deep, rt << 1);
	else
		if (mid < act1)         //细节这里不能取等号,mid==act2,但是不能将问题递归给右子树
			return Q2(act1, act2,mid+1,r, deep, rt << 1 | 1 );
	return max(Q2(act1, act2, l, mid, deep, rt << 1), Q2(act1, act2, mid + 1, r, deep, rt << 1 |1));
}
float Q(int h1, int h2, int act1, int act2, int l, int r, int rt)     //对高度进行定位,并将得到的根节点传给Q2的深度
{
	if (h1 <= l&&r <= h2)
		return Q2(act1, act2, 0, 1000, rt, 1);
	int mid = (l + r) >> 1;
	if (h1>mid)
		return Q(h1, h2, act1, act2, mid + 1, r, rt << 1 | 1);
	else
		if (h2 <= mid)
			return Q(h1, h2, act1, act2, l, mid, rt << 1);
		else
			return max(Q(h1, h2, act1, act2, l, mid, rt << 1), Q(h1, h2, act1, act2, mid+ 1, r, rt << 1 | 1));
}
int  main()
{
	//freopen("in.txt", "r", stdin);
	while (scanf("%d", &N) != EOF&&N)
	{
		build(100, 200, 1);
		char ch;
		while (N--)
		{
			cin >> ch;
			if (ch == 'I')
			{
				int h;
				float x, y;
				cin >> h >> x >> y;
				I(h, (int)(x * 10), y, 100, 200, 1);
			}
			else
			{
				int h1, h2;
				float x1, x2;
				cin >> h1 >> h2 >> x1 >> x2;
				if (h1>h2) {
					int temp = h1; h1 = h2; h2 = temp;

				}
				if (x1>x2) {
					float temp = x1; x1 = x2; x2 =temp;
				}
				float ans = Q(h1, h2, (int)(x1 * 10), (int)(x2* 10), 100, 200, 1);
				if (ans == -1.0) printf("-1\n");
				else printf("%.1lf\n", ans);
			}
		}
	}
	//system("pause");
	return 0;
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值