zkw線段樹


今天自己動手實現了一下zkw版線段樹,做了兩道小題.

zkw版線段樹就是非遞歸版的線段樹,易於理解,實現簡單,速度快.

參考《統計的力量-線段樹全接觸.ppt》http://www.slideshare.net/DanielChou/ss-7792670

 

注意求M的地方:for(M=1;M<=n+1;M*=2);

和老言爭論了半天的n后面是否+1(是否進行越界處理),后來得出的結論是:

+1,浪費空間;

不加,遇到特殊情況有安全隱患,但證明,對於t,如果為偶數,則不進行處理,所以,可以不加.

單點更新:

hdu1166-敵兵布陣(單點更新,區間求和)

View Code
#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(單點更新,區間最值)

View Code
#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;
}

區間更新:

繼續研讀中...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM