bzoj 1568
题意:插入多条射线(起点横坐标为1),以及询问某个x值能截到的最大纵坐标
超哥线段树...
这里蒟蒻不想说话...
推荐两篇博客:
http://blog.csdn.net/u012288458/article/details/51865920
http://www.cnblogs.com/DaD3zZ-Beyonder/p/5478433.html
注意:线段树根的区间范围是[1,50000],手欠习惯[1,n]了,结果操作数读入了个n覆盖了...mdzz
type
rec=record
k,b:double;
flag:boolean;
end;
var
n,x :longint;
i :longint;
ch :char;
s :string;
b,k,ans :double;
t :array[0..200010] of rec;
function cross(k1,b1,k2,b2:double):double;
begin
exit((b2-b1)/(k1-k2));
end;
function max(a,b:double):double;
begin
if a>b then exit(a) else exit(b);
end;
procedure insert(x,l,r:longint;b,k:double);
var
mid:longint;
t1,t2,t3,t4,xx:double;
begin
if not t[x].flag then
begin
t[x].flag:=true; t[x].k:=k; t[x].b:=b;
end else
begin
mid:=(l+r)>>1;
t1:=k*l+b; t2:=t[x].k*l+t[x].b;
t3:=k*r+b; t4:=t[x].k*r+t[x].b;
if (t1<=t2) and (t3<=t4) then exit;
if (t1>=t2) and (t3>=t4) then
begin
t[x].k:=k; t[x].b:=b;
end else
begin
xx:=cross(k,b,t[x].k,t[x].b);
if (t1>=t2) then
begin
if xx<=mid then insert(2*x,l,mid,b,k) else
begin
insert(2*x+1,mid+1,r,t[x].b,t[x].k);
t[x].k:=k; t[x].b:=b;
end;
end else
begin
if xx>mid then insert(2*x+1,mid+1,r,b,k) else
begin
insert(2*x,l,mid,t[x].b,t[x].k);
t[x].k:=k; t[x].b:=b;
end
end;
end;
end;
end;
procedure find(x,l,r,y:longint);
var
mid:longint;
begin
if t[x].flag then ans:=max(ans,t[x].b+t[x].k*y);
if l=r then exit;
mid:=(l+r)>>1;
if y<=mid then find(2*x,l,mid,y) else find(2*x+1,mid+1,r,y);
end;
begin
readln(n);
for i:=1 to n do
begin
read(ch);
s:='';
while ch<>' ' do
begin
s:=s+ch;
read(ch);
end;
if s='Query' then
begin
readln(x);
ans:=0;
find(1,1,50000,x);
writeln(trunc(ans/100));
end else
begin
readln(b,k);
insert(1,1,50000,b-k,k);
end;
end;
end.
bzoj 3165
题意:插入多条线段,第i条插入的线段编号为i,求某个x值能截到最大纵坐标的线段编号,如果多条线段符合要求,输出编号最小的
和上题类似,只不过这次维护的是线段并且是在满足纵坐标最大情况下的最小线段编号,所以维护的细节就多了一些:
(1)如果当前线段不能贯穿当前区间,直接下放给儿子
(2)如果当前区间没有被更新过,直接更新为当前线段
(3)如果当前线段与当前区间的最优相同且编号小于当前区间最优的线段,把当前区间更新为当前线段
(4)其他修改同上题
const
mo=39989;
eps=1e-6;
type
rec=record
l,r,id:longint;
k,b:double;
flag:boolean;
end;
var
m,x,x1,x2,y1,y2 :longint;
lastans,pos,tot :longint;
op :longint;
ans,k,b :double;
i :longint;
t :array[0..160010] of rec;
procedure swap(var a,b:longint);
var
c:longint;
begin
c:=a; a:=b; b:=c;
end;
function cross(k1,b1,k2,b2:double):double;
begin
exit((b2-b1)/(k1-k2));
end;
procedure insert(x,tl,tr,l,r:longint;k,b:double;num:longint);
var
mid:longint;
t1,t2,t3,t4,xx:double;
begin
if (l<=tl) and (r>=tr) then
begin
if not t[x].flag then
begin
t[x].flag:=true; t[x].k:=k; t[x].b:=b; t[x].id:=num; t[x].l:=l; t[x].r:=r
end else
begin
t1:=k*tl+b; t2:=t[x].k*tl+t[x].b;
t3:=k*tr+b; t4:=t[x].k*tr+t[x].b;
mid:=(tl+tr)>>1;
if (abs(t1-t2)<eps) and (abs(t3-t4)<eps) and (t[x].id>num) then
begin
t[x].k:=k; t[x].b:=b; t[x].id:=num; t[x].l:=l; t[x].r:=r;
end else
if (t1<=t2) and (t3<=t4) then exit else
if (t1>=t2) and (t3>=t4) then
begin
t[x].k:=k; t[x].b:=b; t[x].id:=num; t[x].l:=l; t[x].r:=r;
end else
begin
xx:=cross(k,b,t[x].k,t[x].b);
if (t1>=t2) then
begin
if xx<=mid then insert(2*x,tl,mid,l,r,k,b,num) else
begin
insert(2*x+1,mid+1,tr,t[x].l,t[x].r,t[x].k,t[x].b,t[x].id);
t[x].k:=k; t[x].b:=b; t[x].id:=num; t[x].l:=l; t[x].r:=r;
end;
end else
begin
if xx>mid then insert(2*x+1,mid+1,tr,l,r,k,b,num) else
begin
insert(2*x,tl,mid,t[x].l,t[x].r,t[x].k,t[x].b,t[x].id);
t[x].k:=k; t[x].b:=b; t[x].id:=num; t[x].l:=l; t[x].r:=r;
end;
end;
end;
end;
end else
begin
mid:=(tl+tr)>>1;
if r<=mid then insert(2*x,tl,mid,l,r,k,b,num) else
if l>mid then insert(2*x+1,mid+1,tr,l,r,k,b,num) else
begin
insert(2*x,tl,mid,l,r,k,b,num);
insert(2*x+1,mid+1,tr,l,r,k,b,num);
end;
end;
end;
procedure find(x,l,r,y:longint);
var
mid:longint;
begin
if t[x].flag then
if (t[x].k*y+t[x].b>ans) or ((abs(t[x].k*y+t[x].b-ans)<eps) and (t[x].id<pos)) then
begin
ans:=t[x].k*y+t[x].b; pos:=t[x].id;
end;
if l=r then exit;
mid:=(l+r)>>1;
if y<=mid then find(2*x,l,mid,y) else find(2*x+1,mid+1,r,y);
end;
begin
read(m); tot:=0; lastans:=0;
for i:=1 to m do
begin
read(op);
if op=1 then
begin
read(x1,y1,x2,y2); inc(tot);
x1:=(x1+lastans-1) mod mo+1;
x2:=(x2+lastans-1) mod mo+1;
y1:=(y1+lastans-1) mod 1000000000+1;
y2:=(y2+lastans-1) mod 1000000000+1;
if x1>x2 then
begin
swap(x1,x2); swap(y1,y2);
end;
if x1=x2 then
begin
k:=0;
if y1>y2 then b:=y1 else b:=y2;
end else
begin
k:=(y1-y2)/(x1-x2);
b:=y2-k*x2;
end;
insert(1,1,mo,x1,x2,k,b,tot);
end else
begin
read(x);
x:=(x+lastans-1) mod mo+1;
ans:=0; pos:=maxlongint;
find(1,1,mo,x);
if pos=maxlongint then pos:=0;
lastans:=pos;
writeln(pos);
end;
end;
end.
——by Eirlys