[Heoi2013]Segment

Time Limit: 40 Sec  Memory Limit: 256 MB

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)%10^9+1)和((x
1+lastans-1)%39989+1,(y1+lastans-1)%10^9+1) 的线段。
其中lastans为上一次询问的答案。初始时lastans=0。 
 
 

Output

对于每个 0操作,输出一行,包含一个正整数,表示交点最靠上的线段的编号。若不存在与直线相交的线段,答案为0。

Sample Input

6
1 8 5 10 8
1 6 7 2 6
0 2
0 9
1 4 7 6 7
0 5

Sample Output

2
0 3

HINT

对于100%的数据,1 ≤ n ≤ 10^5 , 1 ≤  k, x0, x1 ≤ 39989, 1 ≤ y0 ≤ y1 ≤ 10^9。

思路

代码实现

 1 #include<cstdio>
 2 const int mod2=1e9;
 3 const int mod1=39989;
 4 const int maxn=4e4+10;
 5 const double eps=1e-9;
 6 inline int max_(int x,int y){return x>y?x:y;}
 7 inline void swap_(int&x,int&y){x^=y,y^=x,x^=y;}
 8 inline int dcmp(double x){return (x>eps)-(x<-eps);}
 9 int n,m=0,lastans=0;
10 int opt,x,x0,y0,x1,y1;
11 int a[maxn],id[maxn];
12 int L,R,idx;
13 double K,B;
14 struct node{
15     int id;
16     double k,b;
17     bool v;
18 }t[maxn<<2];
19 void solve(int k,int l,int r){
20     if(t[k].v==0){
21         t[k].k=K,t[k].b=B;
22         t[k].v=1,t[k].id=idx;
23         return;
24     }
25     double y0,y1,y2,y3;
26     y0=t[k].k*l+t[k].b,y1=K*l+B;
27     y2=t[k].k*r+t[k].b,y3=K*r+B;
28     if(dcmp(y1-y0)>0&&dcmp(y3-y2)>0){
29         if(dcmp(K-t[k].k)==0&&dcmp(B-t[k].b)==0) return;
30         t[k].k=K,t[k].b=B,t[k].id=idx;
31         return;
32     }
33     if(dcmp(y1-y0)<=0&&dcmp(y3-y2)<=0) return;
34     int mid=l+r>>1,ls=k<<1,rs=ls|1;
35     solve(ls,l,mid),solve(rs,mid+1,r);
36 }
37 void ins(int k,int l,int r){
38     if(L<=l&&r<=R){
39         solve(k,l,r);
40         return;
41     }
42     int mid=l+r>>1,ls=k<<1,rs=ls|1;
43     if(L<=mid) ins(ls,l,mid);
44     if(R>mid) ins(rs,mid+1,r);
45 }
46 void ins(int x0,int x1,int y0,int y1,int num){
47     L=x0,R=x1,idx=num;
48     K=(0.0+y1-y0)/(0.0+x1-x0),B=y0-x0*K;
49     ins(1,1,maxn);
50 }
51 int aid;
52 double ans;
53 void query(int k,int l,int r,int x){
54     double y=t[k].k*x+t[k].b;
55     if(dcmp(y-ans)==1||(dcmp(y-ans)==0&&t[k].id<aid)) ans=y,aid=t[k].id;
56     if(l==r) return;
57     int mid=l+r>>1,ls=k<<1,rs=ls|1;
58     if(x<=mid) query(ls,l,mid,x);
59     else query(rs,mid+1,r,x);
60 }
61 int main(){
62     scanf("%d",&n);
63     while(n--){
64         scanf("%d",&opt);
65         if(opt==0){
66             scanf("%d",&x);
67             x=(x+lastans-1)%mod1+1;
68             ans=aid=0;
69             query(1,1,maxn,x);
70             if(ans<a[x]||(ans==a[x]&&id[x]<aid)) aid=id[x];
71             printf("%d
",lastans=aid);
72         }
73         if(opt==1){
74             scanf("%d%d%d%d",&x0,&y0,&x1,&y1),m++;
75             x0=(x0+lastans-1)%mod1+1,y0=(y0+lastans-1)%mod2+1;
76             x1=(x1+lastans-1)%mod1+1,y1=(y1+lastans-1)%mod2+1;
77             if(x0>x1) swap_(x0,x1),swap_(y0,y1);
78             if(x0==x1){if(max_(y0,y1)>a[x0]) a[x0]=max_(y0,y1),id[x0]=m;}
79             else ins(x0,x1,y0,y1,m);
80         }
81     }
82     return 0;
83 }
原文地址:https://www.cnblogs.com/J-william/p/8078522.html