膜拜zkw神犇。。。。orz。。。
zkw線段樹的思想是直接找到乙個大區間對應的小區間
由於是自底向上的,所以常數很小(《統計的力量》)
其實我覺得,真正難寫的是區間修改
比如現在造一顆線段樹,支援區間求和,區間修改
zkw線段樹有兩種做法:
一是維護神奇的字首和的字首和
二是沿用遞迴版線段樹的思路,在區間上打標記,然後統計
我太弱,第一種不會。。。於是我就用第二種吧
區間修改:簡單,就在區間上打個標記,順便更新一下遍歷到的區間和,最後當l和r父親相同時,迴圈結束,再把他們的父親們的和更新。
區間求和:先是記一下左邊,右邊的區間裡有幾個元素要加,每次就根據遍歷到的區間的標記更新答案。最後當l和r父親相同時,迴圈結束,再把他們的父親們的標記拿來更新答案
好像有點大話連篇。。。上**好了
const int maxn=262144;
int sumv[maxn],addv[maxn],m;
//sumv 維護區間的和,addv是標記;m不說了吧,地球人都知道
void update(int l,int r,int a)
data[l]+=ln*a;data[r]+=rn*a;
for(ln+=rn,l>>=1;l;l>>=1)
data[l]+=ln*a;//我的父親們~
}int query(int l,int r)
sum+=addv[l]*ln+addv[r]*rn;
for(ln+=rn,l>>=1;l;l>>=1)
sum+=addv[l]*ln;//我的父親們~
return
sum;
}//ps:有錯誤就說一說啊。。。
現在,某人又要求造一顆線段樹支援區間修改,區間最小值
還是沿用區間求和的思路,只是**有點不同
對於更新最小值的操作,不能單純的加減了,而是要根據兒子的值而修改。
const
int maxn=262144;
int data[maxn],addv[maxn],m,n;
//data是區間最小
int query(int l,int r)
lmax+=addv[s];rmax+=addv[t];
lmax=min(lmax,rmax);
for(s>>=1;s;s>>=1)lmax+=addv[s];
return lmax;
}void add(int l,int r,int a)
data[t]=min(data[t<<1]+addv[t<<1],data[t<<1|1]+addv[t<<1|1]);
for(;s;s>>=1)
data[s]=min(data[s<<1]+addv[s<<1],data[s<<1|1]+addv[s<<1|1]);
}
嘿嘿嘿。。。
我的線段樹~
線段樹和zkw線段樹
好啦,我們就開始說說線段樹吧 線段樹是個支援區間操作和查詢的東東,平時的話還是蠻實用的 下面以最基本的區間加以及查詢區間和為例 線段樹顧名思義就是棵樹嘛,葉子節點是每個基本點,它們所對應的父親就是它們的和,具體如下圖 但是對於這樣的線段樹來說,操作所需的時間是遠達不到我們的要求的 會被t 因為我們會...
zkw線段樹小結
zkw zkwzk w線段樹作為迴圈式線段樹具有較小的常數.其實樹狀陣列本質上就是線段樹 下標為 1,n 1,n 1,n 預處理乙個2 k n2 k n 2k n.然後總空間為2k 12 2k 1 2 k 1 4n 2 4n 2k 1 4n 後面令k 2 kk 2 k k 2k 那麼乙個葉子x xx...
鏈結 zkw線段樹
資料結構 走近zkw線段樹 一 資料結構 走近zkw線段樹 二 線段樹的擴充套件之 zkw線段樹 include define lc x x 1 define rc x x 1 1 using namespace std const int maxn 100005 int max int a,int...