zoukankan      html  css  js  c++  java
  • 线段树最全模板

    一定要做的线段树习题汇总

    一、模板

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    #define MAXN 200010
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    int sum[MAXN<<2];
    
    void pushUp(int p)
    {
        sum[p]=max(sum[p<<1],sum[p<<1|1]);
    }
    void build(int l,int r,int p)
    {
        if(l==r){
            scanf("%d",&sum[p]);
            return ;
        }
        int mid=(l+r)>>1;
        build(lson);
        build(rson);
        pushUp(p);
    }
    int query(int l,int r,int p,int a,int b)
    {
        if(l>=a&&b>=r)                             //根据功能代码修改部分
            return sum[p];
    
        int ans=0;
        int mid=(l+r)>>1;
        if(mid>=a)
            ans=max(ans,query(lson,a,b));	      //根据功能代码修改部分
        if(mid<b)
            ans=max(ans,query(rson,a,b));
        return ans;
    }
    void update(int l,int r,int p,int a,int b)
    {
        if(l==r){                                
                                                    //根据功能代码修改部分
    sum[p]=b; return ; } int mid=(l+r)>>1; if(a<=mid) update(lson,a,b); else update(rson,a,b); pushUp(p);}int main(){ int n,m; char ch[5]; //freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { int a,b; build(1,n,1); while(m--) { scanf("%s%d%d",ch,&a,&b); if(ch[0]=='Q') printf("%d ",query(1,n,1,a,b)); else update(1,n,1,a,b); } } return 0;}
    
    

    
    

    二、区间查询,无单点更新

    #include <iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    
    using namespace std;
    const int maxn=200010;
    int sum[maxn<<2];//数组开四倍
    
    int h,w,n;
    
    //p表示下标
    void pushUp(int p)
    {
        //p表示下标,赋值为两个儿子中的最大值
        sum[p]=max(sum[p<<1],sum[p<<1|1]);
    }
    //建树
    void build(int l,int r,int p)
    {
        if(l==r)//区间长度为0时结束递归
        {
            sum[p]=w;
            return ;
        }
        //否则的话,分别递归左儿子和右儿子
        int mid=(r+l)>>1;
        build(l,mid,p<<1);
        build(mid+1,r,p<<1|1);
        pushUp(p);
    }
    //区间查询
    //线段树的最高顶点是表示所有行里面最大的宽度
    int query(int l,int r,int p,int num)
    {
        if(l==r)//找到了一个完全重合的区间
        {
            sum[p]-=num;//进行对应的查询操作
            return l;
        }
        int ans;
        int mid=(r+l)>>1;//下面要注意,先保存ans,然后更新值后再返回
        if(sum[p<<1]>=num)
        {
            ans=query(l,mid,p<<1,num);
        }
        else
        {
    
    
            ans=query(mid+1,r,p<<1|1,num);
        }
        pushUp(p);
        return ans;
    
    }
    int main()
    {
        while(scanf("%d%d%d",&h,&w,&n)!=EOF)
        {
            
        memset(sum,0,sizeof(sum));
        if(h>n)h=n;
        int temp;
        build(1,h,1);//建树区间为[1,h],下标开始序号为1
        for(int i=0;i<n;i++)
        {
            scanf("%d",&temp);
            if(sum[1]<temp)
                cout<<"-1"<<endl;
            else
                cout<<query(1,h,1,temp)<<endl;
        }
        }
        return 0;
    }
    



    三、单点更新+区间求和

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    #define MAXN 50010
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    #define mem(a) memset(a,0,sizeof(a[0]))
    int sum[MAXN<<2];
    
    void pushUp(int p)
    {
        sum[p]=sum[p<<1]+sum[p<<1|1];
    }
    void build(int l,int r,int p)
    {
        if(l==r){
            scanf("%d",&sum[p]);
            return;
        }
        int mid=(l+r)>>1;
        build(lson);
        build(rson);
        pushUp(p);
    }
    int query(int l,int r,int p,int i,int j)
    {
        if(l>=i&&r<=j){
            return sum[p];
        }
        int ans=0;
        int mid=(l+r)>>1;
        if(mid<j) ans+=query(rson,i,j);
        if(mid>=i) ans+=query(lson,i,j);
        return ans;
    }
    void update(int l,int r,int p,int i,int j)
    {
        if(l==r){
            sum[p]+=j;
            return ;
        }
    
        int mid=(l+r)>>1;
        if(mid>=i)
            update(lson,i,j);
        else
            update(rson,i,j);
        pushUp(p);
    }
    
    int main()
    {
        int n,T;
        int cases=1;
        char str[10];
        //freopen("in.txt","r",stdin);
        scanf("%d",&T);
        while(T--)
        {
            mem(sum);
            scanf("%d",&n);
            printf("Case %d:
    ",cases++);
    
            int i,j;
            build(1,n,1);
            while(scanf("%s",str)&&strcmp(str,"End"))
            {
                scanf("%d%d",&i,&j);
                if(strcmp(str,"Query")==0)
                    printf("%d
    ",query(1,n,1,i,j));
                else if(strcmp(str,"Add")==0)
                    update(1,n,1,i,j);
                else if(strcmp(str,"Sub")==0)
                    update(1,n,1,i,-j);
            }
        }
        return 0;
    }
    


    四、区间查询最值+单点更新

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    #define MAXN 200010
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    int sum[MAXN<<2];
    
    void pushUp(int p)
    {
        sum[p]=max(sum[p<<1],sum[p<<1|1]);
    }
    void build(int l,int r,int p)
    {
        if(l==r){
            scanf("%d",&sum[p]);
            return ;
        }
        int mid=(l+r)>>1;
        build(lson);
        build(rson);
        pushUp(p);
    }
    int query(int l,int r,int p,int a,int b)
    {
        if(l>=a&&b>=r)
            return sum[p];
    
        int ans=0;
        int mid=(l+r)>>1;
        if(mid>=a)
            ans=max(ans,query(lson,a,b));
        if(mid<b)
            ans=max(ans,query(rson,a,b));
        return ans;
    }
    void update(int l,int r,int p,int a,int b)
    {
        if(l==r){
            sum[p]=b;
            return ;
        }
        int mid=(l+r)>>1;
        if(a<=mid) update(lson,a,b);
        else update(rson,a,b);
        pushUp(p);
    }
    
    int main()
    {
        int n,m;
        char ch[5];
        //freopen("in.txt","r",stdin);
        while(~scanf("%d%d",&n,&m))
        {
            int a,b;
            build(1,n,1);
            while(m--)
            {
                scanf("%s%d%d",ch,&a,&b);
                if(ch[0]=='Q')
                    printf("%d
    ",query(1,n,1,a,b));
                else
                    update(1,n,1,a,b);
            }
        }
        return 0;
    }
    



  • 相关阅读:
    AtCoder Beginner Contest 205
    Codeforces Round #725 (Div. 3)
    Educational Codeforces Round 110 (Rated for Div. 2)【A
    Codeforces Round #722 (Div. 2)
    AtCoder Beginner Contest 203(Sponsored by Panasonic)
    AISing Programming Contest 2021(AtCoder Beginner Contest 202)
    PTA 520 钻石争霸赛 2021
    Educational Codeforces Round 109 (Rated for Div. 2)【ABCD】
    AtCoder Beginner Contest 200 E
    Educational Codeforces Round 108 (Rated for Div. 2)【ABCD】
  • 原文地址:https://www.cnblogs.com/bryce1010/p/9387102.html
Copyright © 2011-2022 走看看