線段樹2對於Pushdown的理解

2022-07-31 03:06:12 字數 2629 閱讀 7552

最近才把這玩意兒搞出來,**和解說如下:

#include#includeusing namespace std;

const int n=100005;

struct sd

}node[n*2];

int ini[n],root,cnt=0,q;

void buildtree(int &k,int l,int r)

else

}void pushdown(int k)

void modify1(int k,int ql,int qr,int val)

else

node[k].sum=node[node[k].son[0]].sum+node[node[k].son[1]].sum;}}

void modify2(int k,int ql,int qr,int val)

else

node[k].sum=node[node[k].son[0]].sum+node[node[k].son[1]].sum;}}

long long query(int k,int l,int r,int n)

else

方法二:

void pushdown(int k)

wa掉的方法:

void pushdown(int k)

如何理解此pushdown呢(大家可以對照那份wa掉的看)?

首先前兩行是來更新父節點下左右兒子的和一定要遵循*先乘後加*的原則,並且在加的時候,一定不忘乘上區間的長度這樣更新才不會錯!!後面四步是基於要「薪火相傳」的原則,以後pushdown的時候可以pushdown給他們自己的兒子。

所以中間兩步是先來傳乘法(pass)直接用兒子的乘(l&r.pass)乘上父親轉下來的乘(main.pass)。

後面兩步則是傳下父親的加,但是要注意,傳加的時候應該先用兒子原有的加乘上父親的乘(因為我們遵循「*先乘後加*」的原則,在第一階段,原有的加應該會被父親的乘成倍擴大(和區間和(sum)一起)!!!)

關於modify1,modify2中的改變

本人寫程式的時候,可能腦袋有點抽,modify1和操作1不是對應的,modify1對應操作2~~~~~~

先來看一下和乘有關的modify

void modify2(int k,int ql,int qr,int val)

//後面還有省略,這裡只是相對於線段樹1有稍微改變的地方

乘法modify主要要注意的問題,還是要注意要更新加(add)中的東西(我想了一下,介於有pushdown我也覺得沒有那個必要)然後就是正常更新兒子中乘(pass)和總和(sum)。

再來看一下和加有關的modify

}    void modify1(int k,int ql,int qr,int val)

//後面還有省略,這裡只是相對於線段樹1有稍微改變的地方

正常修改兒子中的加(add),但是最後一定不要忘記修改兒子總和時(sum)(因為有pushdown,所以我們不用考慮「先乘後加」原則),只要記住乘上區間長度即可。

最後(幾點提醒)

1、pushdown中一定不要忘了把建立的臨時變數裡的東西傳回node中!!!血的教訓啊!耗了我乙個多小時!!!*

2、modify中pushdown已經幫你做了很多事情了,所以不用think to much!

3、更多警告可以看一下我的線段樹coding caution

p.s:有人可能會問我,為什麼在pushdown中更新下面的總值的時候為什麼不把要更新的點的pass也乘進去,是因為在modify的時候我已經用他原來的pass值更新過一遍了,當然不需要乘進去,那又會有人問,為什麼要把pass的值和add的值又更新到要更新的點的pass和add上呢?這個則是因為後面又要pushdown的時候,一定要連著這個一起pushdown下去。

2018.10.16

下面放乙個寫的比較清晰的線段樹2:

ac code:

#include#define n 100004

#define ll long long

using namespace std;

struct sd

}node[n*10];

ll p,ini[n],root,cnt,n,m;

void update(ll k)

void add_pass(ll k,ll val)

void add_add(ll k,ll val)

void pushdown(ll k)

void buildtree(ll &k,ll l,ll r)

}void modify_pass(ll k,ll l,ll r,ll val)

}void modify_add(ll k,ll l,ll r,ll val)

}ll query(ll k,ll l,ll r)

}int main()

return 0;

}

指標版的線段樹戳這裡☞指標版的線段樹

謝謝採納!

對於線段樹的研究

線段樹 segment tree 是一種特殊的二叉樹,每個節點維護乙個區間,可以用來處理區間更新 單點修改 單點查詢 區間查詢的資料結構。建樹使用分治的思想,將乙個區間 l,r 拆成兩份,分別為 l,mid 與 mid 1,r 分別處理,直到遇到葉子結點 l r 為止,再上推資料 pushup 完成...

DB2 對於序列的部分操作

記錄每次的收穫,有不對的地方歡迎指正 檢視序列 select 序列名 nextval from dual 刪除序列 drop sequence 序列名 建立序列 create sequence seq missionserielno sn as integer start with 7831801 ...

037 對於HIVE架構的理解

0.發展 在hive公布源 之後 公司又公布了presto,這個比較快,是基於記憶體的。impala 3s處理1pb資料。1.hive 能做什麼,與 mapreduce 相比優勢在 關於hive這個工具,hive 學習成本低,入手快,對於熟悉 sql語法的人來說,操作簡單,熟悉。其實,還有乙個,就是...