李超线段树 [Heoi2013]Segment
問題 D: [Heoi2013]Segment
時間限制: 4 Sec 內存限制: 256 MB
題目描述
要求在平面直角坐標系下維護兩個操作:
1.在平面上加入一條線段。記第i條被插入的線段的標號為i。
2.給定一個數k,詢問與直線 x = k相交的線段中,交點最靠上的線段的編號。
輸入
第一行一個整數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。
輸出
對于每個 0操作,輸出一行,包含一個正整數,表示交點最靠上的線段的編號。若不存在與直線相交的線段,答案為0。
樣例輸入
6
1 8 5 10 8
1 6 7 2 6
0 2
0 9
1 4 7 6 7
0 5
樣例輸出
2
0 3
提示
對于100%的數據,1 ≤ n ≤ 10^5 , 1 ≤ k, x0, x1 ≤ 39989, 1 ≤ y0 ≤ y1 ≤ 10^9。
其實這道題就是個板子,李超線段樹。(這個板子就是為了解決這個問題,只不過板子太難了而已,汗顏)
就題論算法把,李超線段樹用來處理向一個區間加有斜率的線段,之后判斷某位置權值最大的線段是哪條之類的問題。而最重要的是多了的insert函數。當分到的區間已屬于這條線段覆蓋的區間是,就要進行更神奇的操作了,去比較當前節點所存的最優線段。先附上代碼。
void insert(int l,int r,int x,int k) {if(!t[x].h)t[x].h=k;if(cmp(t[x].h,k,l))swap(t[x].h,k);if(l==r||a[t[x].h].k==a[k].k)return;int mid=(l+r)/2;double g=(double)(a[t[x].h].b-a[k].b)/(a[k].k-a[t[x].h].k);if(g<l||g>r)return;if(g<=mid)insert(l,mid,x*2,t[x].h),t[x].h=k;else insert(mid+1,r,x*2+1,k); }因為比較分為兩種情況,完全壓制和在區間內有交點。完全壓制不動或直接修改后返回就好了。而對于相交的就必須求出交點,根據交點的位置(其實也就是判斷那條線段在交點那一邊處于優勢)去修改子區間。
對于這段代碼理解還是有點困難(本蒟蒻太水,自己口胡。。)要把本區間右側較大的線段置成本區間最優(我也不是太懂為什么。。望神犇來解釋),若不懂,手動模擬一下過程即可。
還要注意一些細節:直線斜率是否存在,以及兩條線是否平行。。(RE到死)
轉載于:https://www.cnblogs.com/QTY2001/p/7632656.html
總結
以上是生活随笔為你收集整理的李超线段树 [Heoi2013]Segment的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: weka的java环境配置_window
- 下一篇: java语言模拟_Java语言模拟操作系