今天自己動手實現了一下zkw版線段樹,做了兩道小題.
zkw版線段樹就是非遞歸版的線段樹,易於理解,實現簡單,速度快.
參考《統計的力量-線段樹全接觸.ppt》http://www.slideshare.net/DanielChou/ss-7792670
注意求M的地方:for(M=1;M<=n+1;M*=2);
和老言爭論了半天的n后面是否+1(是否進行越界處理),后來得出的結論是:
+1,浪費空間;
不加,遇到特殊情況有安全隱患,但證明,對於t,如果為偶數,則不進行處理,所以,可以不加.
單點更新:
hdu1166-敵兵布陣(單點更新,區間求和)

#include <iostream> #include <stdio.h> #include <string.h> using namespace std; #define N 50005 int M; int T[N*4]; int Query(int s,int t){ int ans=0; for(s=s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1){ if(~s&1) ans+=T[s^1];//如果是左子樹的左孩子,則處理左子樹右孩子 if( t&1) ans+=T[t^1];//如果是右子樹的左孩子,則處理右子樹左孩子 } return ans; } void Add(int n,int V){ for(T[n+=M]+=V,n>>=1;n;n>>=1){ T[n]=T[n+n]+T[n+n+1]; } } void Sub(int n,int V){ for(T[n+=M]-=V,n/=2;n;n/=2){ T[n]=T[n*2]+T[n*2+1]; } } void build_tree(int n){ int i; for(M=1;M<=n+1;M*=2)//計算M for(i=M+1;i<=M+n;i++){ scanf("%d",&T[i]); } for(i=M-1;i>0;i--) T[i]=T[i*2]+T[i*2+1]; } int main() { int t,n,a,b,k=0; char str[10]; scanf("%d",&t); while(t--){ printf("Case %d:\n",++k); memset(T,0,sizeof(T)); scanf("%d",&n); build_tree(n); while(1){ scanf("%s",str); if(strcmp(str,"Query")==0){ scanf("%d%d",&a,&b); cout << Query(a,b) << endl; } else if(strcmp(str,"Add")==0){ scanf("%d%d",&a,&b); Add(a,b); } else if(strcmp(str,"Sub")==0){ scanf("%d%d",&a,&b); Sub(a,b); } else if(strcmp(str,"End")==0){ break; } } } }
hdu1754-I Hate It(單點更新,區間最值)

#include <iostream> #include <stdio.h> #include <string.h> using namespace std; #define N 200005 int T[N*4],M; void seg_build(int n){ int i; for(M=1;M<=n+1;M*=2); for(i=1+M;i<=n+M;i++){ scanf("%d",&T[i]); } for(i=M-1;i;i--) T[i]=max(T[i*2],T[i*2+1]); } void seg_update(int n,int V){ for(T[n+=M]=V,n/=2;n;n/=2) T[n]=max(T[n*2],T[n*2+1]); } int seg_query(int s,int t){ int maxc=-1; for(s=s+M-1,t=t+M+1;s^t^1;s/=2,t/=2){ if(s%2==0) maxc=max(maxc,T[s^1]); if(t%2==1) maxc=max(maxc,T[t^1]); } return maxc; } int main() { int n,m,a,b; char str[5]; while(scanf("%d%d",&n,&m)!=EOF){ memset(T,0,sizeof(T)); seg_build(n); while(m--){ scanf("%s%d%d",str,&a,&b); if(strcmp(str,"U")==0){ seg_update(a,b); } else if(strcmp(str,"Q")==0){ cout << seg_query(a,b) << endl; } } } return 0; }
區間更新:
繼續研讀中...