题目概述
链接: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 不是很明白这个大佬所讲的内容,以后再来看看。。