洛谷 P3372 線段樹 1

2021-08-16 17:55:46 字數 2660 閱讀 8648

今天植樹節,來種一棵線段樹。

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

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

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

輸入格式:

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

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

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

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

操作2: 格式:2 x y 含義:輸出區間[x,y]內每個數的和

輸出格式:

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

輸入樣例:

5 51 5 4 2 3

2 2 4

1 2 3 2

2 3 4

1 1 5 1

2 1 4

輸出樣例:118

20時空限制:1000 ms , 128 m

資料規模:

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

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

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

樣例說明:

題解

一般來說,拿到這道題的第乙個反應應該是硬模,然後一看資料,發現撐不過 o(100000*100000)。『

於是,我們就有了線段樹這種神奇的東西。至於線段樹呢,就是下面這種神奇的東西 ↓

對於線段樹中的每乙個子節點而言,他們都儲存著一段子串行,而對於每乙個葉子節點而言,他們儲存的是單個的資訊元素,而每乙個父節點都是他兩個子節點的整合。

線段樹詳解 (原理,實現與應用)

1.建樹

從根開始,往下建樹。根的掌管範圍為1~n ( l=1,r=n )。當乙個節點掌管著不止乙個資訊元素時,便讓他的左兒子掌管1~mid 

(mid=(l+r)/2),右兒子掌管 mid+1~r 。當 l==r (葉子節點)時,則直接賦值。

2.維護

若乙個節點有左右兒子,則它的值等於它左兒子的值加上它右兒子的值。

建樹** ↓

void bt(int l,int r)

由於我們這樣的記錄方式,在我們每找到一棵子數就需向下推一次 lazy(pushdown 操作)。推的時候我們先修改lazy的值,再分別修改左右兒子的值(倒過來也沒有影響)。

與最後再對線段樹進行維護。

pushdown 

void pushdown(int now)

區間修改** 

void change(int now,int l,int r,int k)

if(tr[now].lz) pushdown(now);

int lc=tr[now].lc,rc=tr[now].rc;

int mid=(tr[now].l+tr[now].r)/2;

if(r<=mid) change(lc,l,r,k);

else if(mid+1<=l) change(rc,l,r,k);

else

tr[now].c=tr[lc].c+tr[rc].c;

}

2.查詢

與修改差不多,要注意的是每找到乙個節點就往下推一次 lazy。

區間查詢** 

ll findsum(int now,int l,int r)

最後,code

#include#include#define ll long long

struct nodetr[400010];

int a[100010];

int n,m,len=0;

void bt(int l,int r)

else if(l==r) tr[now].c=a[l];

}void pushdown(int now)

void change(int now,int l,int r,int k)

if(tr[now].lz) pushdown(now);

int lc=tr[now].lc,rc=tr[now].rc;

int mid=(tr[now].l+tr[now].r)/2;

if(r<=mid) change(lc,l,r,k);

else if(mid+1<=l) change(rc,l,r,k);

else

tr[now].c=tr[lc].c+tr[rc].c;

}ll findsum(int now,int l,int r)

int main()

if(p==2) printf("%lld\n",findsum(1,x,y));

}}

線段樹1 洛谷P3372

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

洛谷 P3372 線段樹1

這是一道模板題 線段樹介紹 1 include2 using namespace std 3int m,n 4int a 100001 5 6struct nodexds 4 100001 4倍空間 1011 一 建樹 12void buid int l,int r,int k 19 int m l...

洛谷 P3372 線段樹 模板1

模板一是區間加修改和區間和 例題 如下 include includeusing namespace std struct tree int rt 1,cnt 2 int n,i,m const int maxa 100000 tree tree maxa 1 結構體模擬線段樹 long long ...