[bzoj3165] [HEOI2013]Segment
阿新 • • 發佈:2019-01-10
每次 class turn 一個 last -o ons 整數 modify
((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。
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,表示插入一條兩個端點為
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
Solution
李超線段樹。
線段樹每個區間記錄一條最優線段。
對於一條線段,以及一條新加的線段,分類討論:
- 若新線段和舊線段沒有交點,更新之後直接退出就好了。
- 否則考慮交點和\(mid\)的位置關系,一邊直接覆蓋,另一邊遞歸處理。
對於每次操作,一共會拆成\(O(\log n)\)個區間,每個區間花費\(O(\log n)\)的代價更新,總復雜度\(O(m\log^2n)\)。
#include<bits/stdc++.h> using namespace std; void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } void print(int x) { if(x<0) putchar('-'),x=-x; if(!x) return ;print(x/10),putchar(x%10+48); } void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} const int maxn = 5e5+10; const int N = 4e4; struct data { int x,y,xx,yy,id; double k,b; double calc(int a) {return k*a+b;} void lm(int a) {y=calc(a),x=a;} void rm(int a) {yy=calc(a),xx=a;} }; int judge(data a,data b,int x) { if(!a.id) return 1; return a.calc(x)==b.calc(x)?a.id>b.id:a.calc(x)<b.calc(x); } int cnt; #define ls p<<1 #define rs p<<1|1 #define mid ((l+r)>>1) struct Segment_Tree { data t[maxn<<2]; void update(int p,int l,int r,data s) { if(s.x<l) s.lm(l); if(s.xx>r) s.rm(r); if(judge(t[p],s,mid)) swap(s,t[p]); if(l==r) return ; if(max(s.y,s.yy)<=min(t[p].y,t[p].yy)) return ; if(s.k>t[p].k) update(rs,mid+1,r,s); else update(ls,l,mid,s); } void modify(int p,int l,int r,data s) { if(s.x<l) s.lm(l); if(s.xx>r) s.rm(r); if(s.x==l&&s.xx==r) return update(p,l,r,s),void(); if(s.x<=mid) modify(ls,l,mid,s); if(s.xx>mid) modify(rs,mid+1,r,s); } data query(int p,int l,int r,int x) { if(l==r) return t[p]; data ans=t[p],res; if(x<=mid) res=query(ls,l,mid,x); else res=query(rs,mid+1,r,x); if(judge(ans,res,x)) ans=res; return ans; } }SGT; int main() { int t;read(t); int lastans=0,id=0; data s; while(t--) { int op,x,y,xx,yy;read(op); if(op==1) { read(x),read(y),read(xx),read(yy); x=(x+lastans-1)%39989+1; y=(y+lastans-1)%1000000000+1; xx=(xx+lastans-1)%39989+1; yy=(yy+lastans-1)%1000000000+1; if(x>xx) swap(x,xx),swap(y,yy); if(x==xx) { y=max(y,yy); s=(data){x,y,xx,y,++id,0,1.0*y}; } else { double k=(double)(y-yy)/(1.0*(x-xx)); s=(data){x,y,xx,yy,++id,k,1.0*y-1.0*x*k}; } SGT.modify(1,1,N,s); } else { read(x);x=(x+lastans-1)%39989+1; write(lastans=SGT.query(1,1,N,x).id); } } return 0; }
[bzoj3165] [HEOI2013]Segment