這題挺揪心的
想了半天為什麼要先乘法後加法
原因是這樣的:
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 #include34#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.求出某區間每乙個數的和 ...