1. 程式人生 > >區改區查標記永久化線段樹

區改區查標記永久化線段樹

pan proc cor 實現 query style 其他 一段 區間

寫完樹剖之後發現還沒有講過區改區查線段樹。。。

標記永久化線段樹的用處:

支持區改區查,嗯,就這樣。(不過聽很多dalao說這種線段樹有利於寫主席樹)

算法核心思路:

對於一段區間加,假如它把線段樹上的一部分完全包涵,那麽我們就把它“永久”的加在這部分上,否則就加在另外一個神奇的地方,這個神奇的地方只有當詢問區間將其完全包涵才能加。

這樣我們就把區間加變成了log級別的。

代碼實現:

procedure update(k,l,r,x,y,z:longint);
var
    mid:longint;
begin
    if (l>=x)and
(r<=y) then begin add_sum[k]:=(add_sum[k]+z)mod p; exit; //完全包涵,把標記永久化。 end; sum[k]:=(sum[k]+(min(r,y)-max(l,x)+1)*z mod p)mod p; //加到一個神奇的地方(我們可以叫它半永久標記,好吧我瞎掰的。。。) mid:=(l+r)>>1; if x<=mid then update(k*2,l,mid,x,y,z); //像普通線段樹的查詢操作一樣繼續更新其他節點,直到需要我們修改的區間全部被永久化為止
if y>mid then update(k*2+1,mid+1,r,x,y,z); end; function query(k,l,r,x,y:longint):longint; var mid:longint; begin if (l>=x)and(r<=y) then exit((sum[k]+(r-l+1)*add_sum[k]mod p)mod p); mid:=(l+r)>>1; query:=(min(r,y)-max(l,x)+1)*add_sum[k]mod p; if x<=mid then
query:=(query+query(k*2,l,mid,x,y))mod p; if y>mid then query:=(query+query(k*2+1,mid+1,r,x,y))mod p; end;

區改區查標記永久化線段樹