要求在平面直角座標系下維護兩個操作:
1.在平面上加入一條線段。記第 i 條被插入的線段的標號為 i
2.給定乙個數 k,詢問與直線 x = k 相交的線段中,交點最靠上的線段的編號。
若有多條線段符合要求,輸出編號最小的線段的編號
明顯的線段樹特徵:
1.有固定的 區間長度,(<=39989)
2.插入元素支援合併,(乙個線段可以拆成兩段線段)
所以我們用線段樹來做這道題。
線段樹維護什麼元素開始不太好想。
發現要求乙個交點最靠上的線段的編號,所以類似維護區間最大值,我們可以在每個區間內維護乙個線段(這個線段兩端座標就是l和r,也就是說,恰好放在這個區間內),保證這個線段和x=mid這條豎直的線的交點的縱座標是有史以來最大的。
我們在區間裡記錄下來這個線段的所屬編號(注意不是線段編號,因為真實情況的一條線段可能會被劈成許多段,但是它們本質上還是同乙個線段,在貢獻答案的時候,還是要輸出它們所代表的真實線段的編號的)。
同時用乙個結構體記錄下來每個線段的x1,x2,y1,y2以及所屬編號hao。
注意由於要劈斷,縱座標不一定是整數,所以y1,y2都是double型別的。
structduanline[n*20
];struct
nodet[
4*(mod1+10)];
發現不需要build,pushup,pushdown,但是。。。我們不能將區間原有線段因為中點處的值小了而「一 棒子打死」,它中點左邊或者右邊的值可能還會對答案產生貢獻。
所以最關鍵的是add操作。
1.特判l==r
已經到了乙個點上。
如果該點之前沒有維護線段,直接維護現在的線段。
如果有,選擇縱座標靠上的直線(點),縱座標相同,選擇編號較小的。
2.如果沒有恰好放在區間裡。
如果不過mid,根據與mid關係左右查詢。
如果過mid,劈兩半分別查詢。
3.如果找到了恰好的區間
如果該區間沒有維護線段,維護該線段。
如果有,
①如果中點處新的優,留下新的,把舊的中,稍微大的一半留下(全劣則淘汰),下放到對應的子區間。
②如果中點處值相同。一般情況選擇新的劈斷的下放(省的建線段)。但是當新的編號較小,並且新的線段的右端點的縱座標大於等於舊的,這時就要劈斷舊的,將舊的右半部分下放。(使得mid處一定取得是新的線段,也就是編號較小的)
③如果中點處舊的優,同理。
查詢的時候,直接沿著一條logn的路徑查詢,時刻更新最大值和ans即可。沒有什麼可多說的。
詳見**:(寫的很醜,但是比較容易看懂)
#includeusingnamespace
std;
const
int n=1e5+10
;const
int mod1=39989
;const
int mod2=1e9;
intn;
inthas;
intla;
intcntpool,cntdel;
intdel[n];
struct
duanline[n*20
];inline
int newnode(int x1,int x2,double y1,double
y2)//
取新節點
void dele(int
x)//
刪除節點,**空間
struct
nodet[
4*(mod1+10)];//
樹double lv(int x1,int x2,double y1,double
y2)//
斜率void add(int x,int l,int r,int x1,int x2,double y1,double y2,int
hh)
else
else
if(mx1==mx2)}}
return
; }
//l==r情況
int mid=(l+r)>>1
;
if(x1!=l||x2!=r)
}//find
else
else
else
if(q2>=y2)
}else
if(d1==d2)//
new = old
else
if(q2<=y2)
else}}
else
if(d1//
new < old
else
if(y2>=q2)}}
}//update
}int
ans;
double
zui;
void query(int x,int l,int r,int
to)
else
if(zui==mx)
return
; }
if(!t[x].id)
else
else
if(zui==d1)
}int mid=(l+r)>>1
;
if(to<=mid) query(x<<1
,l,mid,to);
else query(x<<1|1,mid+1
,r,to);
}}int
main()
else
}return0;
}
upda:2018.12.27
其實這個東西叫做李超線段樹
就是每個區間保留最靠上的直線,實現o(log^2n)的複雜度。
好像應用只有模板題?
李超線段樹
首先來看一道題 heoi2013 segment 可以發現的是,實質上某個 x k 處的最大值只有乙個,因此我們需要盡可能減少計算不優的線段。那麼對於兩條線段 a,b a ne b 它們左右端點橫座標相同,就只會產生如下四種情況 從特殊情況出發,每次我們都插入一條 1,n 的線段。如果是前兩條情況,...
李超線段樹
t4正解李超線段樹?不會,滾過來學 貌似思路並不是很難的亞子 我們可以使用權值線段樹!對於每個區間,我們維護乙個最優線段 顯然對於乙個線段完全覆蓋的區間我們才處理 分四種情況討論 直接賦值 直接賦值 直接滾粗 最複雜的情況,我們考慮將覆蓋該區間最長的線段保留為最優線段 欸嘿?怎麼搞呢?其實只需判斷該...
李超線段樹
可以處理二維平面上加入線段,然後查詢單點最大值。首先我們定義乙個區間的最優勢線段,為區間中點值最大的線段,然後我們發現處理詢問,我們只需要將經過的線段樹節點上的最優勢線段對應的點值取max即可。然後考慮如何處理修改,首先將線段劃分到 o logn 個線段樹節點上。如果當前線段被最優勢線段完全覆蓋,那...