線段樹 區間乘法

2022-02-02 10:12:35 字數 2500 閱讀 1800

如題,已知乙個數列,你需要進行下面三種操作:

將某區間每乙個數乘上\(x\)

將某區間每乙個數加上\(x\)

求出某區間每乙個數的和

第一行包含三個整數\(n,m,p\),分別表示該數列數字的個數、操作的總個數和模數。

第二行包含\(n\)個用空格分隔的整數,其中第\(i\)個數字表示數列第\(i\)項的初始值。

接下來\(m\)行每行包含若干個整數,表示乙個操作,具體如下:

操作\(1\): 格式:\(1 x y k\) 含義:將區間\([x,y]\)內每個數乘上\(k\)

操作\(2\): 格式:\(2 x y k\) 含義:將區間\([x,y]\)內每個數加上\(k\)

操作\(3\): 格式:\(3 x y\) 含義:輸出區間\([x,y]\)內每個數的和對\(p\)取模所得的結果

輸出包含若干行整數,即為所有操作\(3\)的結果。

輸入

5 5 38

1 5 4 2 3

2 1 4 1

3 2 5

1 2 4 2

2 3 5 5

3 1 4

輸出

17

2

【資料範圍】

對於\(30%\)的資料:\(n≤8\),\(m≤10\)

對於\(70%\)的資料:\(n≤10^3\),\(m≤10^4\)

對於\(100%\)的資料:\(n≤10^5\),\(m≤10^5\)

除樣例外,p=571373

這道題和普通的線段樹的不同之處就在於可以用乘法,那麼思考乙個問題,用乘法就考慮到了四則運算的順序問題,要是lazy標誌不及時的推下去,就可能導致乘法在加法還沒有運算的時候乘上去,顯然答案就是錯誤的了,那麼就體應該如何操作呢?

這樣想,要是將乘法和加法用兩個lazy標誌分開計算的話,好像並不好操作,那簡化一下,運用乘法分配率即\((a+lazy[b])*lazy_[c]=a*lazy_[c]+lazy[b]*lazy_[c]\),說白了就是先乘後加,再向下推lazy標記的時候就方便了很多。

#includeconst int maxn = 1e5+5;

long long tree[maxn << 2],lazy[maxn << 2], lazy_[maxn << 2],x[maxn];//線段樹不要忘記要左移兩位,陣列別開小了

int n,m,order,add,mod;

using namespace std;

void build(int rt, int l, int r)

int mid = (l + r) >> 1;

build(rt << 1, l, mid);

build(rt << 1 | 1, mid + 1, r);

tree[rt] = (tree[rt << 1] + tree[rt << 1 | 1])%mod;

}void update(int rt, int l, int r, long long w, long long cheng)

void pushdown(int rt, int l, int r)

void modify(int rt, int l, int r, int s, int t, long long w, long long cheng)

pushdown(rt,l,r);//lazy標記下推

int mid = (l + r) >> 1;

if(mid >= s) modify(rt << 1, l, mid, s, t, w, cheng);

if(mid < t) modify(rt << 1 | 1, mid + 1, r, s, t, w, cheng);

tree[rt] = (tree[rt << 1] + tree[rt << 1 | 1])%mod;

}long long query(int rt, int l, int r, int s, int t)

int mid = (l + r) >> 1;

pushdown(rt, l, r);

long long ans = 0;

if(mid >= s) ans = (ans+query(rt << 1, l, mid, s, t)) % mod;

if(mid < t) ans = (ans + query(rt << 1 | 1, mid + 1, r, s, t)) % mod;

return ans%mod;

}void solve()else if(order == 1)

else }}

int main()

1.mod一定要及時取,該取mod就取,不要少,我就是調這個mod卡了將近兩個小時,也不要取太多,同學有tle的。

2.long long要記得開上,否則就是wa。

3.千萬不要直接推到底,那樣時間效率太低了,本人沒有試過會不會超時,有效率高的的**何必要打效率低的呢?

線段樹的區間加法與區間乘法

題目描述 如題,已知乙個數列,你需要進行下面兩種操作 將某區間每乙個數加上 kk。求出某區間每乙個數的和。輸入格式 第一行包含兩個整數 n,mn,m,分別表示該數列數字的個數和操作的總個數。第二行包含 nn 個用空格分隔的整數,其中第 ii 個數字表示數列第 ii 項的初始值。接下來 mm 行每行包...

線段樹(區間樹)

目錄 為什麼要使用線段樹 什麼是線段樹 線段樹融合介面 線段樹實現 線段樹例題 融合介面 author administrator param public inte ce merger package com.suanfa.segmenttree 線段樹 區間樹 author administra...

線段樹 區間樹

每乙個節點儲存的是乙個區間中相應統計值 在treeindex的位置建立表示區間 l.r 的線段樹 private void buildsegmenttree int treeindex,int l,int r int lefttreeindex leftchild treeindex int rig...