今天植樹節,來種一棵線段樹。
傳送門如題,已知乙個數列,你需要進行下面兩種操作:
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 ...