線段樹模板(結構體)

來源:互聯網
上載者:User

標籤:style   os   io   for   ar   html   amp   log   

線段樹研究了兩天了,總算有了點眉目,今天也把落下的題,補了一下。 貼一份線段樹模板


線段樹的特點:
1. 每一層都是區間[a, b]的一個劃分,記 L = b - a

2. 一共有log2L層
3. 給定一個點p,從根到葉子p上的所有區間都包含點p,且其他區間都不包含點p。
4. 給定一個區間[l; r],可以把它分解為不超過2log2 L條不相交線段的並。


總結來說:線段樹最近本的應用是4點:

1.單點更新:單點替換、單點增減

2.單點詢問

3.區間詢問:區間之和、區間最值

4.區間更新:區間替換、區間增減


下面是 這4個基本操作的模板:(有點兒挫)

單點替換  區間求最大

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>using namespace std;#define N 200004#define MAX INT_MAX#define MIN INT_MINstruct node{int left,right;int num; //}T[4*N];int ans=0;void Creat(int left,int right,int id)//建樹{T[id].left =left;T[id].right =right;T[id].num =0;if(T[id].left ==T[id].right )return ;Creat(left,(left+right)/2,2*id);Creat((left+right)/2+1,right,2*id+1);}void UPdata(int id,int i,int j){if(T[id].left<=i&&T[id].right >=i)T[id].num = j;if(T[id].left ==T[id].right )return;if(i>T[id].right )return;if(i<T[id].left )return;int mid=(T[id].left +T[id].right )/2;if(i<=mid)UPdata(id*2,i,j);elseUPdata(id*2+1,i,j);T[id].num = max(T[id*2].num,T[id*2+1].num);}void query(int id,int l,int r)//區間&&單點查詢,l-r 區間內的所有人{int mid=(T[id].left +T[id].right)/2;if(T[id].left ==l&&T[id].right ==r){if(T[id].num >ans)            ans = T[id].num;return;}if(r<=mid)query(2*id,l,r);else if(l>mid)query(2*id+1,l,r);else{query(2*id,l,mid);query(2*id+1,mid+1,r);}}int main(){    int n,m,x,l,r;    char str[5];    while(scanf("%d%d",&n,&m)!=EOF)    {        Creat(1,n,1);        for(int i = 1;i<=n;i++)        {            scanf("%d",&x);            UPdata(1,i,x);        }        for(int i = 1;i<=m;i++)        {            scanf("%s",str);            if(str[0]=='Q')            {                scanf("%d%d",&l,&r);                ans = -9999999;               query(1,l,r);                printf("%d\n",ans);                ans = -9999999;            }            else if(str[0]=='U')            {                scanf("%d%d",&l,&r);                UPdata(1,l,r);            }        }    }    return 0;}


單點增減  區間求和

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>using namespace std;#define N 50004#define MAX INT_MAX#define MIN INT_MINstruct node{int left,right;int num; //}T[4*N];int ans=0;void Creat(int left,int right,int id)//建樹{T[id].left =left;T[id].right =right;T[id].num =0;if(T[id].left ==T[id].right )return ;Creat(left,(left+right)/2,2*id);Creat((left+right)/2+1,right,2*id+1);}void UPdata(int id,int i,int j)//單點更新{if(T[id].left<=i&&T[id].right >=i)T[id].num +=j;if(T[id].left ==T[id].right )return;if(i>T[id].right )return;if(i<T[id].left )return;int mid=(T[id].left +T[id].right )/2;if(i<=mid)UPdata(id*2,i,j);elseUPdata(id*2+1,i,j);}void query(int id,int l,int r)//區間&&單點查詢{int mid=(T[id].left +T[id].right)/2;if(T[id].left ==l&&T[id].right ==r){ans+=T[id].num ;return;}if(r<=mid)query(2*id,l,r);else if(l>mid)query(2*id+1,l,r);else{query(2*id,l,mid);query(2*id+1,mid+1,r);}}int main(){int t,n,num,l,r,C=1;char str[20];scanf("%d",&t);while(t--){printf("Case %d:\n",C++);scanf("%d",&n);Creat(1,n,1);for(int i=1;i<=n;i++){scanf("%d",&num);UPdata(1,i,num);}while(scanf("%s",str)){if(str[0]=='E')break;else if(str[0]=='Q'){scanf("%d%d",&l,&r);query(1,l,r);printf("%d\n",ans);ans=0;}else if(str[0]=='A'){scanf("%d%d",&l,&r);UPdata(1,l,r);}else if(str[0]=='S'){scanf("%d%d",&l,&r);UPdata(1,l,-r);}       /* else if(str[0]=='D')//單點查詢            {                scanf("%d",&l);                query(1,l,l);                printf("%d\n",ans);                ans = 0;            }*/}}return 0;}


區間增減 


#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#define max(a,b) (a>b)?a:b#define min(a,b) (a>b)?b:a#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1#define LL __int64const int maxn = 500100;using namespace std;#define MAX INT_MAX#define MIN INT_MINstruct node{    int l,r;    LL add,sum;  //add作為一個數的累加和,同時起標記的作用,即lazy數組的作用}T[300010];int a[100005];   //add必須是__int64;void putup(int id){    T[id].sum=T[2*id].sum+T[2*id+1].sum;}void putdown(int id){    if(T[id].add) //更新左右孩子    {        T[2*id].add+=T[id].add;        T[2*id].sum += (T[2*id].r-T[2*id].l+1)*T[id].add;        T[2*id+1].add+=T[id].add;        T[2*id+1].sum += (T[2*id+1].r-T[2*id+1].l+1)*T[id].add;        T[id].add=0;  //取消標幟    }}void creat(int l,int r,int id){    T[id].l=l;    T[id].r=r;    T[id].add=0;    if(l==r)    {        T[id].sum=a[r];        return;    }    int mid=(l+r)>>1;    creat(l,mid,2*id);    creat(mid+1,r,2*id+1);    putup(id);}void update(int from,int to,LL add,int id){    if(from<=T[id].l&&to>=T[id].r)    {        T[id].add +=add;        T[id].sum += (T[id].r-T[id].l+1)*add;        return;    }    putdown(id);    if(from<=T[2*id].r)        update(from,to,add,2*id);    if(to>=T[2*id+1].l)        update(from,to,add,2*id+1);    putup(id);}LL query(int from,int to,int id){    if(from==T[id].l&&to==T[id].r)        return T[id].sum;    putdown(id);    if(from>=T[2*id+1].l)        return query(from,to,2*id+1);    else if(to<=T[2*id].r)        return query(from,to,2*id);    else    return query(from,T[2*id].r,2*id) + query(T[2*id+1].l,to,2*id+1);}int main(){    int n,m,A,B;    LL add;    char str[5];    while(scanf("%d%d",&n,&m)!=EOF)    {        for(int i=1; i<=n; i++)            scanf("%d",&a[i]);        creat(1,n,1);        while(m--)        {            LL ans = 0;            scanf("%s",str);            if(str[0]=='C')            {                scanf("%d%d%I64d",&A,&B,&add);                update(A,B,add,1);            }            else            {                scanf("%d%d",&A,&B);                ans=query(A,B,1);                printf("%I64d\n",ans);            }        }    }}

區間替換

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#define max(a,b) (a>b)?a:b#define min(a,b) (a>b)?b:a#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1#define LL __int64const int maxn = 500100;using namespace std;#define MAX INT_MAX#define MIN INT_MINstruct node{    int l,r;    LL add,sum;  }T[400010];int a[100005];   void putup(int id){    T[id].sum=T[2*id].sum+T[2*id+1].sum;}void putdown(int id){    if(T[id].add)    {        T[2*id].add= T[2*id+1].add= T[id].add;        T[2*id].sum = (T[2*id].r-T[2*id].l+1)*T[id].add;        T[2*id+1].sum = (T[2*id+1].r-T[2*id+1].l+1)*T[id].add;        T[id].add=0;    }}void creat(int l,int r,int id){    T[id].l=l;    T[id].r=r;    T[id].add=0;  //  T[id].sum = 1;    if(l==r)    {        T[id].sum=a[r];        return;    }    int mid=(l+r)>>1;    creat(l,mid,2*id);    creat(mid+1,r,2*id+1);    putup(id);}void update(int from,int to,LL add,int id){    if(from<=T[id].l&&to>=T[id].r)    {        T[id].add = add;        T[id].sum = (T[id].r-T[id].l+1)*add;        return;    }    putdown(id);    if(from<=T[2*id].r)        update(from,to,add,2*id);    if(to>=T[2*id+1].l)        update(from,to,add,2*id+1);    putup(id);}LL query(int from,int to,int id){    if(from==T[id].l&&to==T[id].r)        return T[id].sum;    putdown(id);    if(from>=T[2*id+1].l)        return query(from,to,2*id+1);    else if(to<=T[2*id].r)        return query(from,to,2*id);    else    return query(from,T[2*id].r,2*id) + query(T[2*id+1].l,to,2*id+1);}int main(){    int n,m,A,B;    LL add;    char str[5];    while(~scanf("%d%d",&n,&m))      {       // C++;        for(int i=1; i<=n; i++)            scanf("%d",&a[i]);        creat(1,n,1);        while(m--)        {            scanf("%s",str);            if(str[0]=='T')            {                 scanf("%d%d%I64d",&A,&B,&add);            update(A,B,add,1);            }           else if(str[0]=='Q')           {               scanf("%d%d",&A,&B);               cout<<query(A,B,1)<<endl;           }        }    }}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.