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;
    }
    



  • 相关阅读:
    类型:NodeJs;问题:默认IE的编码为utf8;结果:IE不能自动选择UTF-8编码解决办法
    类型:Java;问题:eclipse配置maven;结果:eclipse配置maven
    类型:Oracle;问题:oracle 时间加减;结果:ORACLE 日期加减操作
    类型:Ajax;问题:ajax调用ashx参数获取不到;结果:ashx文件获取$.ajax()方法发送的数据
    类型:JQuery;问题:ajax调用ashx文件;结果:ashx文件怎么获取$.ajax()方法发送的json数据
    类型:Jquery;问题:jquery调用后台带参数方法;结果:利用JQuery的$.ajax()可以很方便的调用asp.net的后台方法。
    问题:asp.net 点击button按钮调到页面顶部;结果:asp.net点击一个按钮,使页面跳转到本面页上的指定位置
    问题:ClientIDMode属性;结果:ASP.NET 4.0的ClientIDMode属性
    金木水火土五行查询表
    并发编程的基础
  • 原文地址:https://www.cnblogs.com/bryce1010/p/9387102.html
Copyright © 2011-2022 走看看