hdu 1166 敵兵佈陣 (單點更新線段樹模板)
阿新 • • 發佈:2018-12-15
題目連結:哆啦A夢傳送門
題解:
參考連結:https://www.cnblogs.com/TenosDoIt/p/3453089.html
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=50010; struct node{ int val; }segtree[maxn*4]; int arr[maxn]; /* root:當前線段樹的根節點下標 arr: 用來構造線段樹的陣列 istart:陣列的起始位置 iend:陣列的結束位置 */ void build(int root,int istart,int iend) { if(istart==iend){ ///葉子節點 segtree[root].val=arr[istart]; } else{ int mid=(istart+iend)/2; build(root*2,istart,mid); ///遞迴構造左子樹 build(root*2+1,mid+1,iend);///遞迴構造右子樹 ///根據左右子樹根節點的值,更新當前根節點的值 segtree[root].val=segtree[root*2].val+segtree[root*2+1].val; } } /* 功能:線段樹的區間查詢 root:當前線段樹的根節點下標 [nstart, nend]: 當前節點所表示的區間 [qstart, qend]: 此次查詢的區間 */ int query(int root,int nstart,int nend,int qstart,int qend) { ///查詢區間和當前節點區間沒有交集 if(qstart>nend||qend<nstart) return 0; ///當前節點區間包含在查詢區間內 if(qstart<=nstart&&qend>=nend) return segtree[root].val; ///分別從左右子樹查詢,返回兩者查詢結果的較小值 int mid=(nstart+nend)/2; return query(root*2,nstart,mid,qstart,qend) +query(root*2+1,mid+1,nend,qstart,qend); } /* 功能:更新線段樹中某個葉子節點的值 root:當前線段樹的根節點下標 [nstart, nend]: 當前節點所表示的區間 index: 待更新節點在原始陣列arr中的下標 addVal: 更新的值(原來的值加上addVal) */ void updataone(int root,int nstart,int nend,int index,int addval) { if(nstart==nend) { if(index==nstart) ///找到了相應的節點,更新之 { segtree[root].val+=addval; return; } } int mid=(nstart+nend)/2; if(index<=mid) ///在左子樹中更新 updataone(root*2,nstart,mid,index,addval); else updataone(root*2+1,mid+1,nend,index,addval);///在右子樹中更新 ///根據左右子樹的值回溯更新當前節點的值 segtree[root].val=segtree[root*2].val+segtree[root*2+1].val; } char str[10]; int main() { int ncase,n,x,y; scanf("%d",&ncase); int T=0; while(ncase--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&arr[i]); build(1,1,n); printf("Case %d:\n",++T); while(scanf("%s",str)) { if(strcmp(str,"End")==0) break; else if(strcmp(str,"Query")==0) { scanf("%d%d",&x,&y); printf("%d\n",query(1,1,n,x,y)); } else if(strcmp(str,"Add")==0) { scanf("%d%d",&x,&y); updataone(1,1,n,x,y); } else if(strcmp(str,"Sub")==0) { scanf("%d%d",&x,&y); updataone(1,1,n,x,-y); } } } return 0; }
參考神犇kuangbin模板,
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=50010; struct node{ int l,r; int val; }segtree[maxn*4]; ///每個節點表示的範圍 值 int arr[maxn]; void build(int root,int istart,int iend) ///建樹 { segtree[root].l=istart;///儲存此節點的左右範圍 segtree[root].r=iend; if(istart==iend){ segtree[root].val=arr[istart]; } else{ int mid=(istart+iend)>>1; build(root<<1,istart,mid); build(root<<1|1,mid+1,iend); segtree[root].val=segtree[root<<1].val+segtree[root<<1|1].val; } } int query(int root,int qstart,int qend) { if(qstart==segtree[root].l&&qend==segtree[root].r) ///此節點恰好滿足 return segtree[root].val; int mid=(segtree[root].l+segtree[root].r)>>1; if(qend<=mid) return query(root<<1,qstart,qend); ///在左子樹 else if(qstart>mid) return query(root<<1|1,qstart,qend); ///在右子樹 return query(root<<1,qstart,mid)+query(root<<1|1,mid+1,qend); } void updataone(int root,int index,int addval) ///在位置index加上值addval { ///在此節點加上 segtree[root].val+=addval; if(segtree[root].l==index&&segtree[root].r==index) return; int mid=(segtree[root].l+segtree[root].r)>>1; if(index<=mid) ///在左子樹 updataone(root<<1,index,addval); else updataone(root<<1|1,index,addval); } char str[10]; int main() { int ncase,n,x,y; scanf("%d",&ncase); int T=0; while(ncase--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&arr[i]); build(1,1,n); printf("Case %d:\n",++T); while(scanf("%s",str)) { if(strcmp(str,"End")==0) break; else if(strcmp(str,"Query")==0) { scanf("%d%d",&x,&y); printf("%d\n",query(1,x,y)); } else if(strcmp(str,"Add")==0) { scanf("%d%d",&x,&y); updataone(1,x,y); } else if(strcmp(str,"Sub")==0) { scanf("%d%d",&x,&y); updataone(1,x,-y); } } } return 0; }