模板 線段樹 2

2022-05-01 06:09:09 字數 2632 閱讀 5912

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

1.將某區間每乙個數加上x

2.將某區間每乙個數乘上x

3.求出某區間每乙個數的和

輸入格式:

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

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

接下來m行每行包含3或4個整數,表示乙個操作,具體如下:

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

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

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

輸出格式:

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

輸入樣例#1:

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

輸出樣例#1:

17

2

時空限制:1000ms,128m

資料規模:

對於30%的資料:n<=8,m<=10

對於70%的資料:n<=1000,m<=10000

對於100%的資料:n<=100000,m<=100000

(資料已經過加強^_^)

樣例說明:

故輸出應為17、2(40 mod 38=2)

思路:問題主要是沒法分斷是先乘還是先加,我同學說可以能個棧存一下,線段樹里的棧。。。恕我無能。

一般的解決方法是把乘法變成加法。

①:s*lazy+flag.

②:(s+flag)*lazy=s*lazy+flag*lazy.

注意:資料規模,不僅要開long long,還要時常取mod。

**實現:

1 #include2 #include3

using

namespace

std;

4#define ll long long

5ll n,m,mod,a,b,c,d;

6struct natet[800000

];//flag

7void

heritage(ll k)

10 ll lson=k*2,rson=k*2+1

;11 t[lson].s=((t[lson].s*t[k].lazy)%mod+(t[k].flag*(t[lson].r-t[lson].l+1))%mod)%mod;

12 t[lson].flag=((t[lson].flag*t[k].lazy)%mod+t[k].flag)%mod;

13 t[lson].lazy=(t[lson].lazy*t[k].lazy)%mod;//傳遞到左兒子。

14 t[rson].s=((t[rson].s*t[k].lazy)%mod+(t[k].flag*(t[rson].r-t[rson].l+1))%mod)%mod;

15 t[rson].flag=((t[rson].flag*t[k].lazy)%mod+t[k].flag)%mod;

16 t[rson].lazy=(t[rson].lazy*t[k].lazy)%mod;//傳遞到右兒子。

17 t[k].flag=0;t[k].lazy=1;18

}19void

make_tree(ll k,ll l,ll r)

23 ll mid=(l+r)/2;24

make_tree(lson,l,mid);

25 make_tree(rson,mid+1

,r);

26 t[k].s=(t[lson].s+t[rson].s)%mod;27}

28void

interval_add(ll k,ll l,ll r,ll v)

36 ll mid=(t[k].l+t[k].r)/2;37

if(l<=mid) interval_add(lson,l,min(r,mid),v);

38if(r>mid) interval_add(rson,max(l,mid+1

),r,v);

39 t[k].s=(t[lson].s+t[rson].s)%mod;40}

41void

interval_ride(ll k,ll l,ll r,ll v)

49 ll mid=(t[k].l+t[k].r)/2;50

if(l<=mid) interval_ride(lson,l,min(r,mid),v);

51if(r>mid) interval_ride(rson,max(l,mid+1

),r,v);

52 t[k].s=(t[lson].s+t[rson].s)%mod;53}

54ll interval_query(ll k,ll l,ll r)

63int

main()

72if(a==2)76

if(a==3)80

}81return0;

82 }

有沒有感覺很噁心,慢慢來吧。

模板 線段樹 2

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

模板 線段樹2

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

模板 維護序列2(線段樹)

取模取掛可真是令人質壁分離。兩兩乘積和可以直接用兩個區間的區間和相乘再加上兩個區間各自的乘積和得到,而相鄰乘積和直接兩段相加再加上左區間右端點與右區間左端點乘積就好了。注意 mod mod includeusing namespace std typedef long long ll const l...