1. 程式人生 > >[Heoi2013]Segment

[Heoi2013]Segment

給定 技術 center 一行 class ans align 最小 包含

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\n",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 }

[Heoi2013]Segment