線段樹之懶人標記

2021-10-01 12:08:08 字數 2745 閱讀 8721

學了四次線段樹終於把懶標給搞明白了,雖說明白了,但也不是太過熟悉,所以寫乙個部落格來記錄一下

講解:

線段樹的區間修改一般需要用到懶人標記,但是為什麼要用懶人標記,這是乙個很值得思考的問題。例如我們要修改乙個區間的資訊,我們當然可以使用單點修改,來實現區間資訊的修改,但是每次修改的時間複雜度是o(logn),修改n次的時間複雜度為o(nlogn),顯然時間複雜度太高了,所以懶人標記就出現了

講一下懶人標記的作用:

建議:如果你並不能清晰的搞明白線段樹查詢區間的過程,先去把它搞明白再來看下方內容

懶人標記的應用其實不太難理解,假如我們要把區間染色,首先,我們要把1--4區間染成黑色,那麼我們根據線段樹的組成結構,我們會把儲存1--3區間的節點k染色,儲存4--4區間的節點k染色,之後我們要把2--6區間染色,我們會找到1--3區間,因為第二次要染色的區間涉及到了1–3區間,那麼我們就把儲存1--3區間的節點k染色恢復為0,因為它的區間已經被干擾,所以把資訊下傳,直到資訊下穿到不被干擾的區間節點上去,而被干擾的點染成其他色,按此操作進行下去,區間染色即可完成,而時間複雜度只有o(logn),其他型別的區間操作均可以更改乙個區間節點的區間資訊,懶人標記下傳來更新整個區間

來看兩道例題:

區間更新求和

題解:

由於懶人標記只涉及到乙個k點,而區間更新有累加操作,那麼 lazy+=w,模擬之後就是當前更新次數加的數量下傳到了子節點上去

ac**:

#include#include#include#includeusing namespace std;

#define ll long long

const ll maxn=1e6+5;

struct node

tree[maxn*4];

ll c[maxn];

void pushup(ll k)

void pushdown(ll k)

if(tree[k].lazy)//區間可能會被修改多次所以要累加

}void build(ll k,ll l,ll r)//建樹

ll mid=l+r>>1;

build(k<<1,l,mid);

build(k<<1|1,mid+1,r);

pushup(k);

}void update(ll k,ll l,ll r,ll w)

pushdown(k);

ll mid=tree[k].l+tree[k].r>>1;

if(mid>=r)

else if(mid=l&&tree[k].r<=r)

pushdown(k);

ll mid=tree[k].l+tree[k].r>>1;

if(mid>=r)

else if(mid區間染色+離散化

這個就是乙個區間染色,外加一點離散化和小思路

ac**:

#include#include#include#includeusing namespace std;

const int maxn=2e5+5;

//離散化+區間覆蓋

bool vis[maxn];

vectorvec;

int ans,num[maxn],lx[maxn],rx[maxn];

struct node

tree[maxn*4];

int getid(int x)

void pushdown(int k)

if(tree[k].lazy!=-1)

}void build(int k,int l,int r)

int mid=l+r>>1;

build(k<<1,l,mid);

build(k<<1|1,mid+1,r);

}void update(int k,int l,int r,int c)//區間覆蓋顏色c

if(tree[k].lazy!=-1)

pushdown(k);

int mid=tree[k].l+tree[k].r>>1;

if(mid>=r)

else if(mid>1;

query(k<<1,l,mid);

query(k<<1|1,mid+1,r);

}int main()

}sort(vec.begin(),vec.end());

vec.erase(unique(vec.begin(),vec.end()),vec.end());

int len=vec.size();

build(1,1,len);

for(int i=0; ians=0;

query(1,1,len);

printf("%d\n",ans);

}}

線段樹 lazy標記

每個節點代表區間 唯一根節點,也就是全部區間 葉節點是長度為1的子區間,也就是所代表陣列上的乙個點 const int maxn 1e3 struct segmenttree e 4 maxn 建樹 void build int p,int l,int r int mid l r 2 build p...

延遲標記 線段樹

延遲標記 例題以poj3468為例,我們使用線段樹 延遲標記技巧 來實現快速區間修改與區間查詢。具體做法是,我們為每個節點增加乙個延遲標記add,如果add為0,則說明該點的所有子區間都已更新完成,否則說明其子區間仍需要 add。請注意,如果乙個節點被打上 延遲標記 說明該節點曾經被修改過,但其子節...

延遲標記 線段樹

以poj3468為例,我們使用線段樹 延遲標記技巧 來實現快速區間修改與區間查詢。具體做法是,我們為每個節點增加乙個延遲標記add,如果add為0,則說明該點的所有子區間都已更新完成,否則說明其子區間仍需要 add。請注意,如果乙個節點被打上 延遲標記 說明該節點曾經被修改過,但其子節點尚未被更新,...