洛谷P3373 模板 線段樹2

2022-06-04 05:15:07 字數 2184 閱讀 1488

這題挺揪心的

想了半天為什麼要先乘法後加法

原因是這樣的:

1. 加法和乘法順序不一樣會導致不同的結果

比如: (a+b)*c 不等於 a*c + b

而在記錄懶標記的時候,加法和乘法兩種標記放到一起,並不知道哪個先,哪個後。

所以要確定乙個優先順序

我們分析一下兩種順序:

(1) 先加後乘 : (a+b)*c = a*c + b*c

(2) 先乘後加:a*c + b

比較一下,發現,上面的先加後乘相當於下面的式子,在加法上面多乘了乙個c

所以,我們只要是先加後乘的式子,只要加乙個*c就可以轉化為先乘後加的式子

具體的操作就是在新增乘法標記的時候,把加法標記*c就好了

所以,我們就定了乙個總順序:先乘後加

然後在標記傳遞pushdown的時候,兒子的加法標記傳遞完也要保持先乘後加的順序

比如:addv[o] 是父親節點的加法標記, mulv[o] 是父親節點的乘法標記 sumv[o] 是父親節點的求和值, ls表示左兒子, rs表示右兒子

那麼        o

ls           rs

首先,pushdown 的時候,在算兒子的sumv的時候,ls和rs 的懶標記是不用算的(因為我這裡懶標記的定義是:不包含該節點,該節點的兒子加上或乘上的值),所以sumv[ls]和sumv[rs]

還是照樣先加後乘的順序維護

然後,懶標記疊加時候,要把順序考慮進去

舉個例子: a*c+b 這是兒子原來的懶標記

然後加入c和b是父親的懶標記,那麼按照先乘後加應該這麼算:(a*c+b)*c+b

化簡:  =   a*c*c+b*c+b

=    a*(c*c) + (b*c+b)

所以,原來的a重疊懶標記後應該是這樣的,乘法標記是c*c, 加法標記是 b*c+b

所以,懶標記疊加的時候應該是 mulv 照樣乘父親的mulv, addv要先乘一下父親的mulv再加一下父親的addv,這樣才算完

其他的還是該怎麼來就怎麼來,這裡不細說了

完整**:

1 #include2 #include3

4#define ll long long int

5#define ls o<<1

6#define rs o<<1|1

7#define m ((l+r)>>1)89

using

namespace

std;

10const

int maxn = 100010;11

12ll n, m, p;

13 ll a[maxn], sumv[maxn*4], addv[maxn*4], mulv[maxn*4

];14

15 ll add(ll a,ll b)

1819

ll mul(ll a,ll b)

2223 inline void

build(ll o,ll l,ll r) 31}

3233 inline void pushdown(ll o,ll l,ll r)

4950

ll ql,qr,qa,qm;

51 inline void

updatea(ll o,ll l,ll r)

57pushdown(o,l,r);

58if(ql <=m) updatea(ls,l,m);

59if(qr > m) updatea(rs,m+1

,r);

60 sumv[o] =add(sumv[ls], sumv[rs]);61}

6263 inline void

updatem(ll o,ll l,ll r)

70pushdown(o,l,r);

71if(ql <=m) updatem(ls,l,m);

72if(qr > m) updatem(rs,m+1

,r);

73 sumv[o] =add(sumv[ls], sumv[rs]);74}

7576

inline ll query(ll o,ll l,ll r)

8485

intmain() else

if(x == 2

) else

103}

104105

return0;

106 }

洛谷P3373 模板 線段樹2

這題有毒啊,敲了我一晚上加一早上,總算a了。由於有加和乘兩個操作,要用2個lazy陣列。核心難點就是2個lazy陣列會相互影響。因為乘影響加,加不影響乘,所以我們先算乘。include include include include include include include include i...

洛谷 P3373 模板 線段樹 2

如題,已知乙個數列,你需要進行下面三種操作 1.將某區間每乙個數乘上x 2.將某區間每乙個數加上x 3.求出某區間每乙個數的和 第一行包含三個整數n m p,分別表示該數列數字的個數 操作的總個數和模數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3或4個...

線段樹(洛谷P3373模板2)

日常膜拜dalao 財神萬歲!話說這個線段樹今天折磨了我五個小時然後終於發現少打了乙個2.離開學還有4天然而作業一字未動絲毫不慌 ing 原題連線 洛谷線段樹模板2 要求 如題,已知乙個數列,你需要進行下面三種操作 1.將某區間每乙個數乘上x 2.將某區間每乙個數加上x 3.求出某區間每乙個數的和 ...