题目
Description
给出若干条线段,用(x1,y1),(x2,y2)表示其两端点坐标,现在要求支持两种操作:
0 x1 y1 x2 y2
表示加入一条新的线段,(x1,y1)-(x2,y2)
1 x0
询问所有线段中,x坐标在x0处的最高点的y坐标是什么,如果对应位置没有线段,则输出0。
Input
第一行两个正整数N,M为初始的线段个数和操作个数
接下来N行,每行四个整数,表示一条线段
接下来M行,每行为一个操作”0 x1 y1 x2 y2”或”1 x0”
Output
对于每一个询问操作,输出一行,为一个实数,当你的答案与标准答案误差不超过1e-2是,则视为正确。
Sample Input
3 4
0 -1 4 1
4 2 7 2
7 1 8 2
1 4
1 3
0 3 3 6 3
1 3
Sample Output
2.000000
0.500000
3.000000
Data Constraint
对于10%的数据:n,m<=1000
另外20%的数据:所有的1操作都在0操作之后
另外20%的数据:所有线段的两端的x坐标都包含所有的询问的x坐标,你可以将每条线段当做直线处理
对于100%的数据:n<=50000,m<=150000,x1,x2,y1,y2,x0均为整数,0
题解
考虑用一颗树来存储当前的信息,可以用类似线段树的方法,每一个节点储存的是一条线段,而这条线段满足:前面出现过的所有线段在这一段区间内不会出现一半以上都比这条线段y位置要高的情况,那么在查找的时候我们就把经过的线段树中每一条线段在这个位置的最值比较出来就可以了
现在考虑的是如何维护这棵树,在每次新插入一条线段时,我们先把树的横纵坐标调到和这个线段匹配(线段也可能会超过询问的范围,那么就缩小它),然后与线段树里的节点比较一下,不足一半的继续往下递归就可以了
贴代码
const maxn=100000;
tcc=-9999999;
var
tree:array[0..800005,1..2]of extended;
bz:array[0..800005]of boolean;
i,j,l,m,n,x,y,z:longint;
x1,y1,x2,y2,t1:longint;
k,b,ans:extended;
function max(x,y:longint):longint;
begin
if x>y then exit(x) else exit(y);
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x) else exit(y);
end;
procedure change(v,l,r,x,y:l