线段树初见——区间询问与改变最大值
前言
昨天某B組講主席樹(shù),然后就作死的去聽(tīng)了,也沒(méi)聽(tīng)懂(因?yàn)檫B線段樹(shù)都不懂),然后好奇心就去問(wèn)了一下老師線段樹(shù)是個(gè)蛤,然后這篇博客就誕生了。
正題
首先線段樹(shù)就是一個(gè)可以快速區(qū)間改變和詢問(wèn)的東東,實(shí)現(xiàn)方法就是用樹(shù)啦。具體方法看下面。
首先我們講一下例題:
最大值(jzoj1959)
一串序列,有2種操作
1.詢問(wèn)一個(gè)區(qū)間內(nèi)的最大值
2.改變一個(gè)數(shù)的值
這道題明顯沒(méi)有用到區(qū)間改值,那這里先不扯區(qū)間改值:
以下線段樹(shù)草圖
每個(gè)點(diǎn)表示的是一個(gè)區(qū)間內(nèi)的樹(shù)
建樹(shù)代碼
然后是查找某區(qū)間
草圖
分成多份尋找需要的區(qū)間
查找代碼
然后由于這道題只需要改變單個(gè)數(shù)的,瞎水水就過(guò)了
代碼
最大值2(jzoj1960)
依舊是一個(gè)序列兩種操作
1.詢問(wèn)一個(gè)區(qū)間內(nèi)的值
2.讓一個(gè)區(qū)間內(nèi)的值加上一個(gè)數(shù)(可能是負(fù)數(shù))
這里就需要用到區(qū)間改變了
像查找一樣,找到區(qū)間,如果直接改變整棵子樹(shù)會(huì)超時(shí),所以先標(biāo)記,查找時(shí)在下傳
好了,區(qū)間改變代碼
代碼
#include<cstdio> #include<iostream> using namespace std; struct point{long long w,lazy; }tree[400030]; long long ans; int n,m,w,x,y,a[100007],num; int build(int l,int r,int k)//建樹(shù) {if (l==r) return tree[k].w=a[l];int wz=(l+r)/2;return tree[k].w=max(build(l,wz,2*k),build(wz+1,r,2*k+1)); } void find(int l,int r,int x,int y,int k)//查找 {if (x==l && y==r) {ans=max(ans,tree[k].w);return;}if (tree[k].lazy!=0){tree[k*2].w+=tree[k].lazy;tree[k*2].lazy+=tree[k].lazy;tree[k*2+1].w+=tree[k].lazy;tree[k*2+1].lazy+=tree[k].lazy; tree[k].lazy=0;}int wz=(l+r)/2;if (y<=wz) find(l,wz,x,y,2*k);else if (x>wz) find(wz+1,r,x,y,2*k+1);else {find(l,wz,x,wz,2*k);find(wz+1,r,wz+1,y,2*k+1);} } void updata(int l,int r,int x,int y,int num,int k)//改值 {if (l==x && r==y) {tree[k].lazy+=num;tree[k].w+=num;return;}if (tree[k].lazy!=0){tree[k*2].w+=tree[k].lazy;tree[k*2].lazy+=tree[k].lazy;tree[k*2+1].w+=tree[k].lazy;tree[k*2+1].lazy+=tree[k].lazy; tree[k].lazy=0;}int wz=(l+r)/2;if (y<=wz) updata(l,wz,x,y,num,2*k);else if (x>wz) updata(wz+1,r,x,y,num,2*k+1);else {updata(l,wz,x,wz,num,2*k);updata(wz+1,r,wz+1,y,num,2*k+1);}tree[k].w=max(tree[2*k].w,tree[2*k+1].w); } int main() {scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",&a[i]);build(1,n,1);scanf("%d",&m);for (int i=1;i<=m;i++){scanf("%d",&w);if (w==2){scanf("%d%d",&x,&y);//查找ans=-2147483647;find(1,n,x,y,1);printf("%lld\n",ans);}else if (w==1){scanf("%d%d%d",&x,&y,&num);//改值updata(1,n,x,y,num,1);}} } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的线段树初见——区间询问与改变最大值的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 多个PPT文档批量转成图片,处理方法全解
- 下一篇: 做好产品就是联想最好的危机公关做好产品就