bzoj 3165: [Heoi2013]Segment
2015-04-10 15:44
441 查看
Description
要求在平面直角坐标系下维护两个操作:1.在平面上加入一条线段。记第i条被插入的线段的标号为i。
2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号。
Input
第一行一个整数n,表示共n 个操作。接下来n行,每行第一个数为0或1。
若该数为 0,则后面跟着一个正整数 k,表示询问与直线
x = ((k +lastans–1)%39989+1)相交的线段中交点(包括在端点相交的情形)最靠上的线段的编号,其中%表示取余。若某条线段为直线的一部分,则视作直线与线段交于该线段y坐标最大处。若有多条线段符合要求,输出编号最小的线段的编号。
若该数为 1,则后面跟着四个正整数 x0, y0, x 1, y 1,表示插入一条两个端点为
((x0+lastans-1)%39989+1,(y0+lastans-1)%109+1)和((x
1+lastans-1)%39989+1,(y1+lastans-1)%109+1) 的线段。
其中lastans为上一次询问的答案。初始时lastans=0。
Output
对于每个 0操作,输出一行,包含一个正整数,表示交点最靠上的线段的编号。若不存在与直线相交的线段,答案为0。
Sample Input
61 8 5 10 8
1 6 7 2 6
0 2
0 9
1 4 7 6 7
0 5
Sample Output
20 3
HINT
对于100%的数据,1 ≤ n ≤ 10^5 , 1 ≤ k, x0, x1 ≤ 39989, 1 ≤ y0 ≤ y1 ≤ 10^9。线段树。每次修改的时候看与当前区间的最高线段有没有交点。有的话继续往下查找。没有的话判断能否替代
询问的时候自底向上,单次复杂度logn
#include<cstdio> #include<algorithm> using namespace std; struct tree { int l,r; double ll,rr; int s; }tr[200001]; int pl[40001]; inline void build(int p,int l,int r) { tr[p].l=l; tr[p].r=r; if(l!=r) { int mid=(l+r)/2; build(p*2,l,mid); build(p*2+1,mid+1,r); } else pl[l]=p; } inline void change(int p,int x0,int y0,int x1,int y1,double k,int d) { if(x0<=tr[p].l&&tr[p].r<=x1) { double yy0=double(y0)+double(tr[p].l-x0)*k,yy1=yy0+double(tr[p].r-tr[p].l)*k; if(yy0>=tr[p].ll&&yy1>=tr[p].rr) { tr[p].ll=yy0; tr[p].rr=yy1; tr[p].s=d; return ; } if(yy0<=tr[p].ll&&yy1<=tr[p].rr) return ; if(tr[p].l==tr[p].r) { int height=max(tr[p].ll,tr[p].rr); if(yy0>height||yy1>height) { tr[p].ll=yy0; tr[p].rr=yy1; tr[p].s=d; } } else { change(p*2,x0,y0,x1,y1,k,d); change(p*2+1,x0,y0,x1,y1,k,d); } } else { int mid=(tr[p].l+tr[p].r)/2; if(x0<=mid) change(p*2,x0,y0,x1,y1,k,d); if(x1>mid) change(p*2+1,x0,y0,x1,y1,k,d); } } struct ans { double h; int x; }; ans xt,xc; inline void ask(int p,int x) { if(p==0) return ; if(tr[p].l==tr[p].r) { xt.x=tr[p].s; xt.h=max(tr[p].ll,tr[p].rr); ask(p/2,x); } double k=(tr[p].rr-tr[p].ll)/double(tr[p].r-tr[p].l); double height=tr[p].ll+k*double(x-tr[p].l); if(height>xt.h) { xt.h=height; xt.x=tr[p].s; } ask(p/2,x); } int main() { // freopen("segment.in","r",stdin); // freopen("segment.out","w",stdout); int n; scanf("%d",&n); build(1,1,39989); int i; int x; int x0,y0,x1,y1; int lastans=0; int d=0; for(i=1;i<=n;i++) { scanf("%d",&x); if(x==0) { scanf("%d",&x0); x0=((x0+lastans-1)%39989+1); xt=xc; ask(pl[x0],x0); printf("%d\n",xt.x); lastans=xt.x; } else { d++; scanf("%d%d%d%d",&x0,&y0,&x1,&y1); x0=((x0+lastans-1)%39989+1); y0=((y0+lastans-1)%1000000000+1); x1=((x1+lastans-1)%39989+1); y1=((y1+lastans-1)%1000000000+1); if(x0>x1) { int t=x0; x0=x1; x1=t; t=y0; y0=y1; y1=t; } double k=double(y1-y0)/double(x1-x0); change(1,x0,y0,x1,y1,k,d); } } return 0; }
相关文章推荐
- BZOJ 3165: [Heoi2013]Segment
- [李超线段树] BZOJ 3165: [Heoi2013]Segment
- 【BZOJ 3165】【HEOI 2013】Segment
- [李超线段树] BZOJ3165 [Heoi2013]. Segment
- BZOJ 3165 Heoi2013 Segment 线段树
- 【bzoj3165】[Heoi2013]Segment 神奇的线段树
- BZOJ_3165_[Heoi2013]Segment_线段树
- bzoj 3165: [Heoi2013]Segment 线段树
- 【bzoj3165】【HEOI2013】【Segment】【线段树】
- [线段树] BZOJ 3165: [Heoi2013]Segment
- 【李超线段树】BZOJ3165 [Heoi2013]Segment
- 【BZOJ 3165】 [Heoi2013]Segment 李超线段树
- BZOJ3165 : [Heoi2013]Segment
- BZOJ3165: [Heoi2013]Segment
- BZOJ 3165: [Heoi2013]Segment 标记永久化
- BZOJ3165 [Heoi2013]Segment
- bzoj 3165: [Heoi2013]Segment 动态凸壳
- [bzoj3165][Heoi2013]Segment——李超线段树
- 【BZOJ】【P3165】【Heoi2013】【Segment】【题解】【线段树】
- 3165: [Heoi2013]Segment