【NOI2017模拟4.2】查询

来源:互联网 发布:python 抽象类 编辑:程序博客网 时间:2024/06/06 13:20

题目

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:longint;k,b:extended);var    mid:longint;    p,t1,t2,t3,t4:extended;begin    if (l=x) and (r=y) then    begin        if (l=r) and (bz[v]=true) then        begin            if k*l+b>tree[v,1]*l+tree[v,2] then            begin                tree[v,1]:=k;                tree[v,2]:=b;            end;            exit;        end;        mid:=(l+r) div 2;        p:=tree[v,1]*mid+tree[v,2];        if bz[v]=false then        begin            tree[v,1]:=k;            tree[v,2]:=b;            bz[v]:=true;            if l=r then exit;            change(v*2,l,mid,l,mid,k,b);            change(v*2+1,mid+1,r,mid+1,r,k,b);        end else        begin            if k*mid+b>p then            begin                t1:=tree[v,1];                tree[v,1]:=k;                k:=t1;                t1:=tree[v,2];                tree[v,2]:=b;                b:=t1;            end;            p:=tree[v,1]*mid+tree[v,2];            t1:=k*l+b; t2:=tree[v,1]*l+tree[v,2];            t3:=k*mid+b;            if ((t1<=t2) and (t3>p)) or ((t1>t2) and (t3<=p)) then                change(v*2,l,mid,l,mid,k,b) else            begin                t1:=k*r+b; t2:=tree[v,1]*r+tree[v,2];                t3:=k*mid+b; t4:=tree[v,1]*mid+tree[v,2];                if ((t1>t2) and (t3<=t4)) or ((t1<=t2) and (t3>t4)) then                change(v*2+1,mid+1,r,mid+1,r,k,b);            end;        end;    end    else    begin        mid:=(l+r) div 2;        if (y<=mid) then change(v*2,l,mid,x,y,k,b) else        if (x>mid) then change(v*2+1,mid+1,r,x,y,k,b) else        begin            change(v*2,l,mid,x,mid,k,b);            change(v*2+1,mid+1,r,mid+1,y,k,b);        end;    end;end;procedure get(v,l,r,x:longint);var    mid:longint;begin    if (x*tree[v,1]+tree[v,2]>ans) and (bz[v]=true) then ans:=x*tree[v,1]+tree[v,2];    if l=r then    begin        if abs(ans-tcc)<0.000001 then ans:=0;        if abs(ans)<0.0000001 then writeln('0.0000000') else        writeln(ans:0:6)    end        else    begin        mid:=(l+r) div 2;        if x<=mid then get(v*2,l,mid,x) else get(v*2+1,mid+1,r,x);    end;end;begin    assign(input,'query.in'); reset(input);    assign(output,'query.out'); rewrite(output);    readln(n,m);    for i:=1 to n do    begin        readln(x1,y1,x2,y2);        if x1>x2 then        begin            t1:=x1; x1:=x2; x2:=t1;            t1:=y1; y1:=y2; y2:=t1;        end;        if x1=x2 then        begin            k:=0;            b:=max(y1,y2);            if (x1<=0) or (x1>=maxn) then continue;            change(1,1,maxn,x1,x1,k,b);            continue;        end;        k:=(y2-y1)/(x2-x1);        b:=y1-k*x1;        if x1>maxn then continue;        if x2<=0 then continue;        change(1,1,maxn,max(x1,1),min(x2,maxn),k,b);    end;    for i:=1 to m do    begin        read(l);        if l=1 then        begin            readln(l);            ans:=tcc;            get(1,1,maxn,l);        end else        begin            readln(x1,y1,x2,y2);            if x1>x2 then            begin                t1:=x1; x1:=x2; x2:=t1;                t1:=y1; y1:=y2; y2:=t1;            end;            if x1=x2 then            begin                if (x1<=0) or (x1>maxn) then continue;                k:=0;                b:=max(y1,y2);                change(1,1,maxn,x1,x1,k,b);                continue;            end;            k:=(y2-y1)/(x2-x1);            b:=y1-k*x1;            if x1>maxn then continue;            if x2<=0 then continue;            change(1,1,maxn,max(x1,1),min(x2,maxn),k,b);        end;    end;    close(input); close(output);end.
0 0
原创粉丝点击