hdu 1823 - 二维线段树
当操作符为‘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)
其实对于二维线段树,可以这样理解:
母树保存x轴上面的信息;子树保存当y轴上的信息;
所以我们每当对母树进行更新或者建立的时候,都要对母树所对应的子树进行所有的建立;
就相当于,先考虑x轴的范围,然后当x的范围一定时,在考虑对于x范围内的y值范围!^_^
#include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> using namespace std; const int N=2050; struct sub_node { int la,ra; int max; }; struct node { int l,r; sub_node T[N]; }; node TT[N]; void sub_build(int rt,int sub_rt,int la,int ra) { TT[rt].T[sub_rt].la=la; TT[rt].T[sub_rt].ra=ra; TT[rt].T[sub_rt].max=-1; if(la==ra) return; int mid=(la+ra)>>1; sub_build(rt,sub_rt<<1,la,mid); sub_build(rt,sub_rt<<1|1,mid+1,ra); } void build(int rt,int l,int r,int la,int ra) { TT[rt].l=l; TT[rt].r=r; sub_build(rt,1,la,ra); if(l==r) return; int mid=(l+r)>>1; build(rt<<1,l,mid,la,ra); build(rt<<1|1,mid+1,r,la,ra); } void sub_update(int rt,int sub_rt,int active,int love) { if(TT[rt].T[sub_rt].la==TT[rt].T[sub_rt].ra) { TT[rt].T[sub_rt].max=max(TT[rt].T[sub_rt].max,love); return; } int mid=(TT[rt].T[sub_rt].la+TT[rt].T[sub_rt].ra)>>1; if(active<=mid) sub_update(rt,sub_rt<<1,active,love); else sub_update(rt,sub_rt<<1|1,active,love); TT[rt].T[sub_rt].max=max(TT[rt].T[sub_rt].max,love); } void update(int rt,int height,int active,int love) { sub_update(rt,1,active,love); if(TT[rt].l==TT[rt].r) return; int mid=(TT[rt].l+TT[rt].r)>>1; if(height<=mid) update(rt<<1,height,active,love); else update(rt<<1|1,height,active,love); } int sub_query(int rt,int sub_rt,int a1,int a2) { if(TT[rt].T[sub_rt].la==a1&&TT[rt].T[sub_rt].ra==a2) return TT[rt].T[sub_rt].max; int mid=(TT[rt].T[sub_rt].la+TT[rt].T[sub_rt].ra)>>1; if(a2<=mid) return sub_query(rt,sub_rt<<1,a1,a2); else if(a1>mid) return sub_query(rt,sub_rt<<1|1,a1,a2); else return max(sub_query(rt,sub_rt<<1,a1,mid),sub_query(rt,sub_rt<<1|1,mid+1,a2)); } int query(int rt,int h1,int h2,int a1,int a2) { if(TT[rt].l==h1&&TT[rt].r==h2) return sub_query(rt,1,a1,a2); int mid=(TT[rt].l+TT[rt].r)>>1; if(h2<=mid) return query(rt<<1,h1,h2,a1,a2); else if(h1>mid) return query(rt<<1|1,h1,h2,a1,a2); else return max(query(rt<<1,h1,mid,a1,a2),query(rt<<1|1,mid+1,h2,a1,a2)); } int main() { int n,i; int active,love; char str[5]; while(~scanf("%d",&n)) { if(n==0) break; build(1,100,200,0,1000); for(i=0;i<n;i++) { scanf("%s",str); if(str[0]=='I') { int h; double a,l; scanf("%d%lf%lf",&h,&a,&l); active=(int)10*a; love=(int)10*l; update(1,h,active,love); } else { int h1,h2; double a1,a2; scanf("%d%d%lf%lf",&h1,&h2,&a1,&a2); int aa1=(int)10*a1; int aa2=(int)10*a2; if(h1>h2) swap(h1,h2); if(aa1>aa2) swap(aa1,aa2); double ans=query(1,h1,h2,aa1,aa2); if(ans<0) puts("-1"); else printf("%.1lf\n",ans/10); } } } return 0; }
解题思路:
把身高看做一维,活泼度看做一维,做基本的二维线段树区间求最大,小数点先乘10把它化为整数才能做线段树
#include<cstdio> #include<iostream> #include<cstring> #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 using namespace std; typedef long long ll; const int mx = 1e3 + 10; int sum[mx][mx*3],m,n; int L1,R2,L2,R1,u,flag,val[mx][mx]; void update_y(int l,int r,int rt,int d) { if(l==r){ if(flag) sum[d][rt] = max(sum[d][rt],u); else sum[d][rt] = max(sum[d<<1][rt],sum[d<<1|1][rt]); return ; } int mid = (l+r)>>1; if(R1<=mid) update_y(lson,d); else update_y(rson,d); sum[d][rt] = max(sum[d][rt<<1],sum[d][rt<<1|1]); } void update_x(int l,int r,int rt) { if(l==r){ update_y(1,m,1,rt); flag = 0; return; } int mid = (l+r)>>1; if(L1<=mid) update_x(lson); else update_x(rson); update_y(1,m,1,rt); } int query_y(int l,int r,int rt,int d) { if(L2<=l&&r<=R2) return sum[d][rt]; int mid = (l+r)>>1; int ans = -1; if(L2<=mid) ans = max(ans,query_y(lson,d)); if(R2>mid) ans = max(ans,query_y(rson,d)); return ans; } int query_x(int l,int r,int rt) { if(L1<=l&&r<=R1) return query_y(1,m,1,rt); int mid = (l+r)>>1; int ans = -1; if(L1<=mid) ans = max(ans,query_x(lson)); if(R1>mid) ans = max(ans,query_x(rson)); return ans; } int main() { int t; char c[100]; double x1,y1; n = 110,m = 1005; while(scanf("%d",&t)&&t) { memset(sum,-1,sizeof(sum)); while(t--){ scanf("%s",c); if(c[0]=='I'){ scanf("%d%lf%lf",&L1,&x1,&y1); L1 -= 99,R1 = x1*10+1,u = y1*10; flag = 1; update_x(1,n,1); }else{ scanf("%d%d%lf%lf",&L1,&R1,&x1,&y1); L1 -= 99,R1 -= 99; L2 = x1*10+1,R2 = y1*10+1; if(L1>R1) swap(L1,R1); if(L2>R2) swap(L2,R2); int ans = query_x(1,n,1); if(ans==-1) puts("-1"); else printf("%.1lf\n",1.0*ans/10); } } } return 0; }