線段樹學習
這個題來看,線段樹分為建樹,更新,查詢。
1.建樹
void
build
(ll p,ll l,ll r)
ll mid=
(l+r)
>>1;
build
(lson
(p),l,mid)
;build
(rson
(p),mid+
1,r)
;push_up_sum
(p);
}void
push_up_sum
(ll p)
這段**的意義是,先將每個節點的lazytag標記置為0,然後再遞迴建樹。裡面的push_up_sum代表這個線段樹記錄的是區間的和.
2.更新
inline
void
f(ll p,ll l,ll r,ll k)
inline
void
push_down
(ll p,ll l,ll r)
inline
void
update
(ll p,ll l,ll r,ll x,ll y,ll k)
push_down
(p,l,r)
;//如果l,r有更新的,那就更新
ll mid=
(r+l)
>>1;
if(x<=mid)
update
(lson
(p),l,mid,x,y,k);if
(y>mid)
update
(rson
(p),mid+
1,r,x,y,k)
;// printf("777\n");
push_up_sum
(p);
//把子節點更新的push上來.
}
lazytag的主要意義是,p節點的值更新後,tag[p]是更新p節點子節點的資訊。如果後續沒有查詢p的子節點,那麼就不用更新p的子節點。這樣的好處就是大大減少了時間複雜度。
而push_down函式就要在每一次使用p子節點的時候呼叫,用來更新p的子節點。只更新下一層
f函式是用k值更新p節點所對應的[l,r]區間,並用tag[p]儲存資訊。只更新本層
update函式是已知要對[x,y]的每個元素更新k,而利用傳參可以知道目前更新目標是p節點對應的[l,r]
1.如果[l,r]包含於[x,y],那麼這個區間就需要更新,呼叫f函式
2.如果[l,r]不包含與[x,y],此時要呼叫子節點了,所以先呼叫push_down函式。然後在有交集的情況下,從左邊區間和右邊區間分別尋找[x,y]的子區間,並更新。
3.查詢
這個和更新差不多,不再贅述
ll query
(ll p,ll l,ll r,ll x,ll y)
ll mid=
(l+r)/2
;// printf("%d\n",mid);
// printf("7\n");
push_down
(p,l,r);if
(x<=mid) res+
=query
(lson
(p),l,mid,x,y);if
(y>mid) res+
=query
(rson
(p),mid+
1,r,x,y)
;return res;
}
完整**
#include
using namespace std;
#define mxn 1000005
typedef
long
long ll;
ll dat[mxn<<1]
;ll tag[mxn<<1]
,a[mxn]
;//tag[p]==0,說明這個節點不需要被修改.tag[p]==k,說明這個節點的子區間需要被加上自變數為k的影響
inline ll lson
(ll rt)
inline ll rson
(ll rt)
void
push_up_sum
(ll p)
void
build
(ll p,ll l,ll r)
ll mid=
(l+r)
>>1;
build
(lson
(p),l,mid)
;build
(rson
(p),mid+
1,r)
;push_up_sum
(p);
}void
push_up_min
(ll p)
inline
void
f(ll p,ll l,ll r,ll k)
inline
void
push_down
(ll p,ll l,ll r)
inline
void
update
(ll p,ll l,ll r,ll x,ll y,ll k)
push_down
(p,l,r)
;//如果l,r有更新的,那就更新
ll mid=
(r+l)
>>1;
if(x<=mid)
update
(lson
(p),l,mid,x,y,k);if
(y>mid)
update
(rson
(p),mid+
1,r,x,y,k)
;// printf("777\n");
push_up_sum
(p);
//把子節點更新的push上來.
}ll query
(ll p,ll l,ll r,ll x,ll y)
ll mid=
(l+r)/2
;// printf("%d\n",mid);
// printf("7\n");
push_down
(p,l,r);if
(x<=mid) res+
=query
(lson
(p),l,mid,x,y);if
(y>mid) res+
=query
(rson
(p),mid+
1,r,x,y)
;return res;
}int
main
(void
)// printf("111");
build(1
,1,n);
while
(m--)if
(a1==2)
}// system("pause");
return0;
}
P3372 模板 線段樹 1
題 include includeusing namespace std typedef long long ll ll n,m,ans,x,y,op,val 因為下面有的函式需要用到x,y,val值,懶得傳參,故直接寫為全域性變數 const int n 100000 struct nodetre...
P3372 模板 線段樹 1
題目描述 如題,已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數加上x 2.求出某區間每乙個數的和 輸入輸出格式 輸入格式 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3或4個整數...
P3372 模板 線段樹 1
如題,已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數加上x 2.求出某區間每乙個數的和 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3或4個整數,表示乙個操作,具體如下 操作1 ...