分析:
第一个想法就是按照身高排序
身高相同的就按照活泼度排序
询问就是一个区间[x1~x2,y1~y2]的最大值
如果我们把每一个妹子按照我们的排列顺序写成一个矩阵,那么询问的就是一个子矩阵的最大值
子矩阵最大值,一个二维问题
我就想能不能用CDQ做,
但是因为是一个区间,每一维都是有上下界的,而且询问的是最大值,CDQ不是很好搞
那我们就用最暴力的一种方法:二维线段树
直接暴力维护矩阵最小值
但是浮点数怎么搞
原则:精度精度,乘大数
因为所有输入的浮点数,均只有一位小数
我们都*10,这样就变成了int,可以直接搞了
tip
注意初始清零
注意两维的范围
询问区间不一定有序。。。
WA了好久,最后发现是insert的时候有问题
相同身高,同样活泼的人可能很多,但是我们肯定留下缘分值最高的
代码中把缘分值也转化成了int,实际上可以直接用double做
(然而显然int用的空间少啊)
INT:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int INF=1e9;
int MX[1003][5003],n,ans;
void update(int x,int y)
{
MX[x][y]=max(MX[x][y<<1],MX[x][y<<1|1]);
}
void insert_y(int bh,int l,int r,int x,int z,int xrt)
{
if (l==r)
{
if (z!=-1) MX[xrt][bh]=max(MX[xrt][bh],z);
else MX[xrt][bh]=max(MX[xrt<<1][bh],MX[xrt<<1|1][bh]);
return;
}
int mid=(l+r)>>1;
if (x<=mid) insert_y(bh<<1,l,mid,x,z,xrt);
else insert_y(bh<<1|1,mid+1,r,x,z,xrt);
update(xrt,bh);
}
void insert_x(int bh,int l,int r,int x,int y,int z)
{
if (l==r)
{
insert_y(1,0,1000,y,z,bh);
return;
}
int mid=(l+r)>>1;
if (x<=mid) insert_x(bh<<1,l,mid,x,y,z);
else insert_x(bh<<1|1,mid+1,r,x,y,z);
insert_y(1,0,1000,y,-1,bh);
}
void ask_y(int bh,int l,int r,int L,int R,int xrt)
{
if (l>=L&&r<=R)
{
ans=max(ans,MX[xrt][bh]);
return;
}
int mid=(l+r)>>1;
if (L<=mid) ask_y(bh<<1,l,mid,L,R,xrt);
if (R>mid) ask_y(bh<<1|1,mid+1,r,L,R,xrt);
}
void ask_x(int bh,int l,int r,int xl,int xr,int yl,int yr)
{
if (l>=xl&&r<=xr)
{
ask_y(1,0,1000,yl,yr,bh);
return;
}
int mid=(l+r)>>1;
if (xl<=mid) ask_x(bh<<1,l,mid,xl,xr,yl,yr);
if (xr>mid) ask_x(bh<<1|1,mid+1,r,xl,xr,yl,yr);
}
int main()
{
while (scanf("%d",&n)!=EOF&&n)
{
memset(MX,-1,sizeof(MX));
char s[5];
int h,o;
double ha,yf;
for (int i=1;i<=n;i++)
{
scanf("%s",s);
if (s[0]=='I')
{
scanf("%d%lf%lf",&h,&ha,&yf);
insert_x(1,100,200,h,(int)10*ha,(int)10*yf);
}
else
{
scanf("%d%d%lf%lf",&h,&o,&ha,&yf);
int r1=(int)10*ha,r2=(int)10*yf;
ans=-INF;
ask_x(1,100,200,min(h,o),max(h,o),min(r1,r2),max(r1,r2));
if (ans>=0) printf("%0.1lf\n",(double)ans/10);
else printf("-1\n");
}
}
}
return 0;
}
DOUBLE:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
double MX[1003][5003],ans;
int n;
void update(int x,int y)
{
MX[x][y]=max(MX[x][y<<1],MX[x][y<<1|1]);
}
void build_y(int bh,int l,int r,int xrt)
{
MX[xrt][bh]=-1.0;
if (l==r) return;
int mid=(l+r)>>1;
build_y(bh<<1,l,mid,xrt);
build_y(bh<<1|1,mid+1,r,xrt);
}
void build_x(int bh,int l,int r)
{
build_y(1,0,1000,bh);
if (l==r) return;
int mid=(l+r)>>1;
build_x(bh<<1,l,mid);
build_x(bh<<1|1,mid+1,r);
}
void insert_y(int bh,int l,int r,int x,double z,int xrt)
{
if (l==r)
{
if (z!=-1.0) MX[xrt][bh]=max(MX[xrt][bh],z);
else MX[xrt][bh]=max(MX[xrt<<1][bh],MX[xrt<<1|1][bh]);
return;
}
int mid=(l+r)>>1;
if (x<=mid) insert_y(bh<<1,l,mid,x,z,xrt);
else insert_y(bh<<1|1,mid+1,r,x,z,xrt);
update(xrt,bh);
}
void insert_x(int bh,int l,int r,int x,int y,double z)
{
if (l==r)
{
insert_y(1,0,1000,y,z,bh);
return;
}
int mid=(l+r)>>1;
if (x<=mid) insert_x(bh<<1,l,mid,x,y,z);
else insert_x(bh<<1|1,mid+1,r,x,y,z);
insert_y(1,0,1000,y,-1.0,bh);
}
void ask_y(int bh,int l,int r,int L,int R,int xrt)
{
if (l>=L&&r<=R)
{
ans=max(ans,MX[xrt][bh]);
return;
}
int mid=(l+r)>>1;
if (L<=mid) ask_y(bh<<1,l,mid,L,R,xrt);
if (R>mid) ask_y(bh<<1|1,mid+1,r,L,R,xrt);
}
void ask_x(int bh,int l,int r,int xl,int xr,int yl,int yr)
{
if (l>=xl&&r<=xr)
{
ask_y(1,0,1000,yl,yr,bh);
return;
}
int mid=(l+r)>>1;
if (xl<=mid) ask_x(bh<<1,l,mid,xl,xr,yl,yr);
if (xr>mid) ask_x(bh<<1|1,mid+1,r,xl,xr,yl,yr);
}
int main()
{
while (scanf("%d",&n)!=EOF&&n)
{
build_x(1,100,200);
char s[5];
int h,o;
double ha,yf;
for (int i=1;i<=n;i++)
{
scanf("%s",s);
if (s[0]=='I')
{
scanf("%d%lf%lf",&h,&ha,&yf);
insert_x(1,100,200,h,(int)(10*ha),yf);
}
else
{
scanf("%d%d%lf%lf",&h,&o,&ha,&yf);
int r1=(int)(10*ha),r2=(int)(10*yf);
ans=-1.0;
ask_x(1,100,200,min(h,o),max(h,o),min(r1,r2),max(r1,r2));
if (ans!=-1.0) printf("%.1lf\n",ans);
else printf("-1\n");
}
}
}
return 0;
}
因为题目是单点插入,查询最大值,我一开始觉得可以用树状数组搞
(树状数组神啊,可以维护最大值啊)
但是打算写的时候,发现了一个问题:
树状数组支持单点修改,区间查询
但是如果我们用树状数组维护最大值的话,我们只能得到前缀最大值
是没有办法得到区间的最大值的(毕竟树状数组一个结点可能维护多个位置)
那如果用RMQ呢
说不定有什么二维RMQ呢
然后我一查,wdmy,真的有。。。
但是RMQ没有办法动态添加啊
看来还是二维线段树↑