學了四次線段樹終於把懶標給搞明白了,雖說明白了,但也不是太過熟悉,所以寫乙個部落格來記錄一下講解:
線段樹的區間修改一般需要用到懶人標記,但是為什麼要用懶人標記,這是乙個很值得思考的問題。例如我們要修改乙個區間的資訊,我們當然可以使用單點修改,來實現區間資訊的修改,但是每次修改的時間複雜度是講一下懶人標記的作用: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。請注意,如果乙個節點被打上 延遲標記 說明該節點曾經被修改過,但其子節點尚未被更新,...