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

2021-09-25 19:58:10 字數 1378 閱讀 7488

題目描述

你現在有乙個陣列 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 這個樣子

2. 查詢: 形如 11 ll rr , 要求輸出此時的 ∑ri=lai∑i=lrai 的值

一開始當然整個陣列都是0啦

輸入描述

第一行乙個整數q表示操作總數

接下來q行, 每行乙個操作(格式參考題目描述)

輸出描述

對於每個查詢, 輸出一行, 表示此時的 ∑ri=lai∑i=lrai 的值

樣例輸入

3

0 1 2

0 3 4

1 1 4

樣例輸出

6
資料範圍

1<=q,l,r<=105

最近給學弟學妹講線段樹,發現以前這道題並沒有補,就給補上了。

對於乙個區間每個位置要加上對應的數   [1 2 3 4 5 6 ...]  

若把上述區間分成左右區間就變成了         [1 2 3]     [4 5 6] 

a           b

由於  [4 5 6] =  [1 2 3] + [3 3 3]

所以需要兩個懶惰標記,lazy1記錄這個區間裡有多少個等差數列(a部分),lazy2記錄這個區間的每個數要加上多少(b部分)

**如下:

#include#define n 100010

#define ll long long

using namespace std;

struct node

eg[n];

ll sum[n<<2],lazy1[n<<2],lazy2[n<<2];

void pushup(int o)

void pushdown(int o,ll len)

}void update(int x,int y,int l,int r,int o)

pushdown(o,(ll)r-l+1);

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

if(x<=mid)update(x,y,l,mid,o<<1);

if(y>mid)update(x,y,mid+1,r,o<<1|1);

pushup(o);

}ll query(int x,int y,int l,int r,int o)

int main()

for(int i=0;ireturn 0;

}

C E 等差數列求和

題目 要求給定乙個整數 n,求從 0 到 n 之間所有整數相加之和。解1 使用 for 迴圈依次遞加。include int main void int sum int x return result 解2 題目所求實際上為乙個首項為 0,末項為 n,公差為 1 的等差數列,根據等差求和公式 s n...

C E 等差數列求和

題目 要求給定乙個整數 n,求從 0 到 n 之間所有整數相加之和。解1 使用 for 迴圈依次遞加。include int main void int sum int x return result 解2 題目所求實際上為乙個首項為 0,末項為 n,公差為 1 的等差數列,根據等差求和公式 s n...

牛牛的等差數列 線段樹

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