HDU - 1823 Luck and Love结题报告(二维线段树)(模板)

题目概述

链接:https://vjudge.net/problem/HDU-1823

思路分析

第一道二维线段树。
因为涉及到升高和活泼度两个变量,所以需要二维线段树维护。因为活泼度和缘分值都是浮点数,因为不想存浮点数,所以*10变成整数。
其实二维线段树就是树套树,我们的思路就是:先把当作一个一维的线段树,先找出要更新的或者访问的节点的第一个坐标,之后再用相同的方法处理第二个坐标。这次主要的问题是没有抓住这个思路去分析,需要理解这种思想。

完整代码

#include <iostream>
#include <cstdio>
#include <algorithm> 
#include <cstdio>
using namespace std;
int tree[205<<2][1005<<2];//其实就是树套一个树,确定完第一维后再来线段树维护第二维 
void subbuild(int xrt,int l,int r,int rt){//最好不要用memset,因为需要全部设置为-1 
	tree[xrt][rt]=-1;
	if(l!=r){
		int m=(l+r)>>1;
		subbuild(xrt,l,m,rt<<1);
		subbuild(xrt,m+1,r,rt<<1|1);
	}
}

void build(int l,int r,int rt){
	subbuild(rt,1,1000,1);
	if(l==r) return;
	int m=(l+r)>>1;
	build(l,m,rt<<1);
	build(m+1,r,rt<<1|1);
}

void subchange(int xrt,int a,int l,int r,int rt,int val){//第一位中要改变的位置(xrt)传给第二维,再更新第二维 
 	if(l==r)
	{
		tree[xrt][rt]=max(tree[xrt][rt],val);
		return;
	}
    int m=(l+r)>>1;
    if(a<=m) subchange(xrt,a,l,m,rt<<1,val);
    else subchange(xrt,a,m+1,r,rt<<1|1,val);
    tree[xrt][rt]=max(tree[xrt][rt<<1],tree[xrt][rt<<1|1]);
}
void change(int h,int a,int l,int r,int rt,int val){//单点修改,先确定第一维度中要更新的位置 
	subchange(rt,a,1,1000,1,val);
	if(l!=r){
		int m=(l+r)>>1;
		if(h<=m) change(h,a,l,m,rt<<1,val);
		else change(h,a,m+1,r,rt<<1|1,val);
	}
}

int subquery(int xrt,int a1,int a2,int l,int r,int rt){//区间查询 
	if(a1<=l&&a2>=r) return tree[xrt][rt];
	int m=(l+r)>>1;
	int ans=-1;//因为有可能找不到,所以设置为-1 
	if(a1<=m) ans=max(ans,subquery(xrt,a1,a2,l,m,rt<<1));
	if(a2>m) ans=max(ans,subquery(xrt,a1,a2,m+1,r,rt<<1|1));
	return ans;
}

int query(int h1,int h2,int a1,int a2,int l,int r,int rt){
	if(h1<=l&&h2>=r) return subquery(rt,a1,a2,1,1000,1);
	int m=(l+r)>>1;
	int ans=-1;
	if(h1<=m) ans=max(ans,query(h1,h2,a1,a2,l,m,rt<<1));
	if(h2>m) ans=max(ans,query(h1,h2,a1,a2,m+1,r,rt<<1|1));
	return ans;
}

int main()
{
	int t;
	while(scanf("%d",&t)&&t!=0){
		build(100,200,1);
		while(t--){
			char cmd[2];
			cin>>cmd;
			if(cmd[0]=='I'){
				int h;
				double a,l;
				cin>>h>>a>>l;
				int aa=a*10,ll=l*10;
				change(h,aa,100,200,1,ll);
			}
			if(cmd[0]=='Q'){
				int h1,h2;
				double a1,a2,l;
				cin>>h1>>h2>>a1>>a2;
				if(h1>h2) swap(h1,h2);
				if(a1>a2) swap(a1,a2);//看到大佬博客上有才加上的,不加会wa 
				int ans=query(h1,h2,a1*10,a2*10,100,200,1);
				if(ans==-1) cout<<-1<<endl;
				else printf("%.1lf\n",ans/10.0);
			}
		}
	}
	return 0;
 } 

ps:https://www.bilibili.com/video/av93930905?t=2423 不是很明白这个大佬所讲的内容,以后再来看看。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值