**和思路來自:傳送門
建樹模板、
//一:線段樹基本概念
//1:概述
//線段樹,類似區間樹,是乙個完全二叉樹,它在各個節點儲存一條線段(陣列中的一段子陣列),
//主要用於高效解決連續區間的動態查詢問題,由於二叉結構的特性,它基本能保持每個操作的複雜度為o(lgn)!
//性質:父親的區間是[a,b],(c=(a+b)/2)左兒子的區間是[a,c],右兒子的區間是[c+1,b],線段樹需要的空間為陣列大小的四倍
#includeusing
namespace
std;
const
int qq=256
;int segtree[(qq<<2)+10
];int
array[qq];
void build(int node,int l,intr)}
intmain()
//此模板用於查詢區間最小值、
對應查詢函式模板、
//區間查詢int query(int node, int begin, int end, int left, int right);
//(其中node為當前查詢節點,begin,end為當前節點儲存的區間,left,right為此次query所要查詢的區間)
//主要思想是把所要查詢的區間[a,b]劃分為線段樹上的節點,然後將這些節點代表的區間合併起來得到所需資訊
//比如前面乙個圖中所示的樹,如果詢問區間是[0,2],或者詢問的區間是[3,3],不難直接找到對應的節點回答這一問題。但並不是所有的提問都這麼容易回答,
int query(int node,int begin,int end,int l,intr)
//可見,這樣的過程一定選出了盡量少的區間,它們相連後正好涵蓋了整個[left,right],沒有重複也沒有遺漏。
//同時,考慮到線段樹上每層的節點最多會被選取2個,一共選取的節點數也是o(log n)的,因此查詢的時間複雜度也是o(log n)。
//線段樹並不適合所有區間查詢情況,它的使用條件是「相鄰的區間的資訊可以被合併成兩個區間的並區間的資訊」。即問題是可以被分解解決的。
對應單點更新模板、
void updata(int node,int l,int r,int ind,int add) //單結點更新、
int m = (l+r) >> 1
if(ind<=m) updata(node<<1
,l,m,ind,add);
else updata((node<<1)+1,m+1
,r,ind,add);
segtree[node]=min(segtree[node<<1],segtree[(node<<1)+1
]);}
//回溯的時候修改每個結點的最小值、
rmq 查詢區間最值下標、
#include#includeusing
namespace
std;
#define maxn 100
#define maxind 256 //
線段樹節點個數
//構建線段樹,目的:得到m陣列.
void build(int node, int b, int e, int m, int
a)
}
//找出區間 [i, j] 上的最小值的索引
int query(int node, int b, int e, int m, int a, int i, int
j)
intmain()
;
build(
1, 0, sizeof(a)/sizeof(a[0])-1
, m, a);
cout
<1, 0, sizeof(a)/sizeof(a[0])-1, m, a, 0, 5)
0;
}
連續區間修改或單結點更新的動態查詢問題
#include #includeusing
namespace
std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define root 1 , n , 1
#define ll long long
const
int maxn = 111111
;
ll add[maxn
<<2
];
ll sum[maxn
<<2
];
void pushup(int
rt)
void pushdown(int rt,int
m)
}
void build(int l,int r,int
rt)
int m = (l + r) >> 1
;
build(lson);
build(rson);
pushup(rt);
}
void update(int l,int r,int c,int l,int r,int
rt)
pushdown(rt , r - l + 1
);
int m = (l + r) >> 1
;
if (l <=m) update(l , r , c , lson);
if (m pushup(rt);
}
ll query(
int l,int r,int l,int r,int
rt)
pushdown(rt , r - l + 1
);
int m = (l + r) >> 1
;
ll ret = 0
;
if (l <= m) ret +=query(l , r , lson);
if (m < r) ret +=query(l , r , rson);
return
ret;
}
intmain()
else
}
return
0;
}
線段樹 小整理
求區間和 ll sum maxn 2 儲存區間和 ll add maxn 2 懶惰標記 ll a maxn 用於輸入儲存資料求區間和的函式 void pushup int x 建立線段樹 void buildtree int l,int r,int rt int m l r 1 buildtree ...
線段樹入門整理
線段樹 interval tree 是把區間逐次二分得到的一樹狀結構,它反映了包括歸併排序在內的很多分治演算法的問題求解方式。宣告 1 include2 include3 const int maxnode 2097152 4 const int max 1000003 5 struct noden...
線段樹入門 資料整理
c題題解,專題訓練一 講解線段樹從入門到高階 線段樹開闢的空間一般是需要儲存的資料的4倍。線段樹使用了二分的思想 我自己認為 把區域進行不斷的二分。她能把一些對於區間 或者線段 的修改 維護,從 o n 的時間複雜度變成 o logn 目前常見的模板中,大體有兩種形式 使用簡單陣列,在函式引數表表示...