首先发表下做完后的感受:这题真他妈操蛋!!!一个简单的二维线段树,搞了一下午啊啊。。
思路:首先根据身高建一棵线段树,然后在每个节点上再以活泼度建一棵线段树,并记录每个区间的最大缘分值。
重点说细节了:在查询时可能会有A1>A2,H1>H2;然后就是插入数据时可能会有缘分值为0的数据,所以初始化时不要初始化为0;可能会插入身高和活泼度相同但缘分值不同的数据,因此还需要比较一下;最后一点,我写(int)(A*10)竟然会wrong,最后看了讨论改为(int)((A+eps)*10)就过了。
#include <iostream> #include<cstdio> using namespace std; const double eps=1e-6;//看了讨论后加的。。。 struct subtree//活泼度 { int l, r; double MAXL;//最大缘分值 }; struct tree//身高 { int l, r; struct subtree node[4100]; }p[410]; void createnode(int i,int l,int r,int rt) { p[i].node[rt].l=l; p[i].node[rt].r=r; p[i].node[rt].MAXL=-1.0; if(l==r) return; int mid=(l+r)>>1; createnode(i,l,mid,rt<<1|1); createnode(i,mid+1,r,(rt<<1)+2); } void createtree(int l,int r,int rt) { p[rt].l=l; p[rt].r=r; createnode(rt,0,1000,0); if(l==r) return; int mid=(l+r)>>1; createtree(l,mid,rt<<1|1); createtree(mid+1,r,(rt<<1)+2); } void insertnode(int i,int A,double L,int rt) { if(p[i].node[rt].l==p[i].node[rt].r&&p[i].node[rt].l==A) { if(p[i].node[rt].MAXL<L) p[i].node[rt].MAXL=L; return; } int mid=(p[i].node[rt].l+p[i].node[rt].r)>>1; if(A<=mid) insertnode(i,A,L,rt<<1|1); else insertnode(i,A,L,(rt<<1)+2); p[i].node[rt].MAXL=max(p[i].node[rt<<1|1].MAXL,p[i].node[(rt<<1)+2].MAXL); } void insert(int H,int A,double L,int rt) { insertnode(rt,A,L,0);//在包含该值的节点上都要插入 if(p[rt].l==H&&p[rt].l==p[rt].r) return; int mid=(p[rt].l+p[rt].r)>>1; if(H<=mid) insert(H,A,L,rt<<1|1); else insert(H,A,L,(rt<<1)+2); } float querynode(int i,int A1,int A2,int rt) { if(p[i].node[rt].l==A1&&p[i].node[rt].r==A2) return p[i].node[rt].MAXL; int mid=(p[i].node[rt].l+p[i].node[rt].r)>>1; if(A2<=mid) return querynode(i,A1,A2,rt<<1|1); else if(A1>mid) return querynode(i,A1,A2,(rt<<1)+2); else return max(querynode(i,A1,mid,rt<<1|1),querynode(i,mid+1,A2,(rt<<1)+2)); } float query(int H1,int H2,int A1,int A2,int rt) { if(p[rt].l==H1&&p[rt].r==H2) return querynode(rt,A1,A2,0); int mid=(p[rt].l+p[rt].r)>>1; if(H2<=mid) return query(H1,H2,A1,A2,rt<<1|1); else if(H1>mid) return query(H1,H2,A1,A2,(rt<<1)+2); else return max(query(H1,mid,A1,A2,rt<<1|1),query(mid+1,H2,A1,A2,(rt<<1)+2)); } int main() { int m,H1,H2; double A1,A2,L; char op[3]; while(scanf("%d",&m),m) { createtree(0,100,0); while(m--) { scanf("%s",op); if(op[0]=='I') { scanf("%d%lf%lf",&H1,&A1,&L); H1-=100;//都统一减掉100,这样H的范围就是0-100 insert(H1,int((A1+eps)*10),L,0); } else { scanf("%d%d%lf%lf",&H1,&H2,&A1,&A2); if(H1>H2) swap(H1,H2); if(A1>A2) swap(A1,A2); H1-=100;H2-=100; //不知道此处为何非要加上eps double ans=query(H1,H2,int((A1+eps)*10),int((A2+eps)*10),0); if(ans==-1.0) printf("-1\n"); else printf("%.1lf\n",ans); } } } return 0; }