區間變成等差數列(線段樹)

2022-06-08 17:03:12 字數 1821 閱讀 5066

keven 特別喜歡線段樹,他給你乙個長度為 n的序列,對序列進行m次操作。

操作有兩種:

1lrk :表示將下標在 [l,r]區間內的數字替換成 [k,k+1,…,k+r−l]

2lr :表示查詢區間 [l,r]的區間和

第一行兩個整數 n、m,表示序列的長度和操作次數(1<=n,m<=2e5)

第二行 n個整數,表示序列的初始值 a1,a2,…an(1<=ai<=2e5)

接下來 m行,每行三或四個數字,若第乙個數字是 1,則表示操作 1,反之則表示操作 2。

(1<=l<=r<=n,1<=k<=2e5)

對於每個操作 2,輸出一行乙個整數表示區間和。

示例1複製

5 5

1 1 1 1 1

2 1 5

1 1 5 1

2 1 5

1 1 3 3

2 1 3

複製

5

1512

第一次1操作後,序列是1 2 3 4 5

第二次1操作後,序列是3 4 5 4 5

這個一眼看過去要用線段樹寫,最關鍵的是懶惰標記怎麼傳:

在這裡懶惰標記每一段區間的首項,

那麼傳懶惰標記的時候就是:

假如傳的是p,那麼2*p那一段的首項是等於p的首項的,2*p+1那一段那一段的首項是p的首相加2*p那一段的長度

if

(t[p].lazy)

#include#include

using

namespace

std;

typedef

long

long

ll;const

int maxn=1e6+100

;struct

nodet[maxn];

ll a[maxn];

void jianshu(int p,int l,int

r)

int mid=(l+r)/2

; jianshu(

2*p,l,mid);

jianshu(

2*p+1,mid+1

,r);

t[p].sum=t[2*p].sum+t[2*p+1

].sum;

} void pushdown(int

p)//

if(t[p].lazy)

}void update(int p,int l,int

r,ll k)

int mid=(l+r)/2

; pushdown(p);

if(l<=mid)

if(r>mid)

t[p].sum=t[2*p].sum+t[2*p+1

].sum;

}ll query(

int p,int l,int

r)

int mid=(t[p].l+t[p].r)/2

; pushdown(p);

ll ans=0

;

if(l<=mid)

if(r>mid)

return

ans;

} int

main()

jianshu(

1,1,n);

intop,x,y;

ll k;

for(int i=1;i<=m;i++)

else

}}

牛牛的等差數列 線段樹

這裡的突破口在於小於等於25且大於等於3的質數連乘在1e8左右,所以,我們可以在操作上,將其看作對1e8去求模,而不是對每個都進行預處理。時間複雜度 include include include include include include include include include inc...

線段樹專題 樹上等差數列

題目大意 思路 線段樹維護區間的a1和an,公差為1。poj3468 include define ll long long using namespace std define max node 400005 define max 100005 struct node node max node ...

求和問題(線段樹維護等差數列)

題目描述 你現在有乙個陣列 aa 我們定義如下的兩種操作 1.修改 形如 00 ll rr 效果為對所有 l i rl i r 執行 ai i l 1 ai i l 1 直觀地說就是al 1,al 1 2,al 2 3 ar r l 1al 1,al 1 2,al 2 3 ar r l 1 這個樣子...