1. 程式人生 > >HDU 1166 - 敵兵布陣 - [單點修改、區間查詢zkw線段樹]

HDU 1166 - 敵兵布陣 - [單點修改、區間查詢zkw線段樹]

n) get 線段 sca tdi input 區間 shu ac代碼

題還是那個題:http://www.cnblogs.com/dilthey/p/6827959.html

不過我們今天換一種線段樹實現來做這道題;

關於zkw線段樹的講解:https://zhuanlan.zhihu.com/p/29876526(而且我還在文章裏被@了,超開心的ヾ(≧?≦*)ヾ)

可以說是講解非常的清楚了!

AC代碼(包含了擁有節點更新、區間查詢功能的zkw線段樹模板):

 1 #include<cstdio>
 2 #include<cstring>
 3 #define MAX 131072
 4 int n,m;
 5 int tree[MAX];
 6 void
pushup(int rt){tree[rt]=tree[rt<<1]+tree[rt<<1|1];} 7 void build() 8 { 9 for(m=1;m<n;m<<=1); 10 for(int i=m;i<=2*m-1;i++) tree[i]=0;//初始化葉子結點 11 for(int i=m+1;i<=m+n;i++) scanf("%d",&tree[i]);//存儲單點值到葉子結點 12 for(int i=m-1;i;i--) pushup(i); 13 } 14 void update(int
pos,int val) 15 { 16 pos+=m; 17 tree[pos]+=val;//更新葉子結點 18 for(pos>>=1;pos;pos>>=1) pushup(pos); 19 } 20 int query(int l,int r) 21 { 22 int ret=0; 23 for(l=l+m-1,r=r+m+1;l^r^1;l>>=1,r>>=1) 24 { 25 if(~l&1) ret+=tree[l^1]; 26 if(r&1
) ret+=tree[r^1]; 27 } 28 return ret; 29 } 30 int main() 31 { 32 int t; 33 scanf("%d",&t); 34 for(int kase=1;kase<=t;kase++) 35 { 36 scanf("%d",&n); 37 build(); 38 printf("Case %d:\n",kase); 39 char input[7]; 40 while(1) 41 { 42 scanf("%s",input); 43 if(input[0]==E) break; 44 if(input[0]==Q) 45 { 46 int l,r; 47 scanf("%d%d",&l,&r); 48 printf("%d\n",query(l,r)); 49 } 50 if(input[0]==A) 51 { 52 int pos,x; 53 scanf("%d%d",&pos,&x); 54 update(pos,x); 55 } 56 if(input[0]==S) 57 { 58 int pos,x; 59 scanf("%d%d",&pos,&x); 60 update(pos,-x); 61 } 62 } 63 } 64 }

PS. MAX=131072這個也是比較有講究的,因為n最大是50000,所以對應的我們的m算出來是65536,所以這棵完全二叉樹最後一個葉子節點的編號為2 * 65536 - 1 = 131072 - 1.

PS2.其實不難發現,zkw線段樹也是一種用空間換取時間和代碼量的做法.

HDU 1166 - 敵兵布陣 - [單點修改、區間查詢zkw線段樹]