給定序列,支援區間加、求區間和。
線段樹的基本思路(線段樹模板嘛,不懂得看題解第一,dalao講解超詳細的)
#includeusing namespace std;
#define ll long long
int maxn=1000001;
unsigned ll n,m,a[maxn],ans[maxn<<2],lazytag[maxn<<2];
開頭還用解釋嗎qaq
inline ll 左兒子
inline ll 右兒子
void 輸入
void 傳遞
void 建樹
void 當前處理懶標記
void 傳遞懶標記
void 更新
ll 求和
//當然在資料較小的時候可以用int,看著順眼
以上是各函式的框架,都是線段樹的基本函式。
int main()
case 2: }
return 0;
}
主函式的設計思路還是比較簡單的,不過要注意輸入輸出的優化,cincout可能會tle吧,雖然沒試過2333
接下來是填好了的主函式!一定要自己打一遍再看哦~
真的自己打了嗎???
int main()
case 2:
return 0;
}
這些函式都是啥???接著往下看吧owo
先看比較簡單的找左右兒子
根據二叉樹的性質
父親節點fa的左右兒子
分別是 fa<<2 和 fa<<2|1
這是zhaungbi優秀的位運算
表示fa2 和 fa2+1
你可以先不用理解它是什麼意思
記住它的含義就好了
void shuru()
簡單可愛的輸入
void pushup(ll x)
void buildtree(int x,int l,int r)
ll mid=(l+r)>>1;
build(leftchild(x),l,mid);
build(rightchild(x),mid+1,r);
pushup(p);
}
二分的方法建樹
如果是葉子節點,那麼它的值就是自己
如果是父親節點,就是它的兒子的和
初始化懶標記為0,表示暫時沒有向下傳遞的資料
void lazy(ll x,ll l,ll r,ll k)
void pushdown(ll x,ll l,ll r)
void update(ll l,ll r,ll l,ll r,ll x,ll k)
//不完全包含
pushdown(x,l,r);//處理懶標記,排除影響
ll mid=(l+r)>>1;
if(l<=mid)update(l,r,l,mid,leftchild(x),k);
if(r>mid) update(l,r,mid+1,r,rightchild(x),k);
pushup(x);
}ll querysum(ll a,ll b,ll l,ll r ll x)
接下來求和和更新的操作類似
都是判斷所求區間與當前區間的包含關係
完全包含當前區間比較好辦
不完全包含的情況用二分查詢,降低時間複雜度owo
嘛測試點資訊
洛谷P3372 線段樹模板
線段樹講的很詳細的部落格 鏈結 includeusing namespace std typedef long long ll const int maxn 100005 ll dat maxn 儲存資料 ll tree maxn 2 儲存線段樹的陣列常開成資料的4倍大小 ll add maxn 2...
洛谷 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 ...
洛谷 P3372 模板 線段樹 1
題目描述 如題,已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數加上x 2.求出某區間每乙個數的和 輸入格式 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3或4個整數,表示乙個操作...