zoukankan      html  css  js  c++  java
  • 线段树五种基本操作代码模板

    这个模板是从大神:https://www.cnblogs.com/TheRoadToTheGold/p/6254255.html的博客上摘抄过来的

    注意:一开始要定义全局变量,n是节点数,m是操作数,查询操作都是void型的,所以需要有ans来承载答案,每个操作初始都要把ans置0,a,b是左右区间,p,a,b是输入

    模板里的区间修改和单点修改都是值加上一个数,如果是变成一个数把函数里的+=改成=就好

    另外找到一个模板好像比较好,先码住吧。

    题目链接:https://nanti.jisuanke.com/t/40852

    #include<bits/stdc++.h>
    using namespace std;
    string s;
    int dat[4000005],lazy[4000005],a[4000005];
    int n;
    void pushup(int rt)
    {
        dat[rt]=dat[2*rt]+dat[2*rt+1];
    };
    void build(int l,int r,int rt)
    {
        if (l==r-1)
        {
            dat[rt]=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid,r,rt<<1|1);
        pushup(rt);
    }
    void pushdown(int rt,int l,int r)
    {
        if (lazy[rt]!=-1)
        {
            lazy[2*rt]=lazy[2*rt+1]=lazy[rt];
            dat[2*rt+1]=dat[2*rt]=lazy[rt]*(r-l)/2;
            lazy[rt]=-1;
        }
    }
    void update(int L,int R,int l,int r,int rt,int c)
    {
        if (L<=l&&r<=R)
        {
            dat[rt]=c*(r-l);
            lazy[rt]=c; 
            return;
        }
        int mid=(l+r)>>1;
        pushdown(rt,l,r);
        if (L<mid) update(L,R,l,mid,rt<<1,c);
        if (R>mid) update(L,R,mid,r,rt<<1|1,c);
        pushup(rt);
    }//更新pushup pushdown都需要 
    int  query(int L,int R,int l,int r,int rt)
    {
        if (L<=l&&r<=R)
            return dat[rt];
        int mid=(l+r)>>1;
        pushdown(rt,l,r);//若更新只有点更新,不需要这句
        int ANS=0;
        if (L<mid) ANS+=query(L,R,l,mid,rt<<1);
        if (R>mid) ANS+=query(L,R,mid,r,rt<<1|1);
        return ANS;
    }//查询只需要pushdown 
    int main()
    {
        cin>>s;
        int n_=s.size();
        for(int i=1;i<=n_;i++)
        a[i]=s[i-1]-'0';
        n=1;
        while(n<n_)
        n*=2;
        build(1,n+1,1);
        memset(lazy,-1,sizeof(lazy));
        int m;
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            int l,r,flag;
            scanf("%d %d %d",&l,&r,&flag);
            int t=query(l,r+1,1,1+n,1);
            if(flag==0)
            {
                update(l,r+1-t,1,1+n,1,0);
                update(r-t+1,r+1,1,1+n,1,1);
            }
            else
            {
                update(l,l+t,1,1+n,1,1);
                update(l+t,r+1,1,1+n,1,0);
            }
        }
        for(int i=1;i<=n_;i++)
        printf("%d",query(i,i+1,1,1+n,1));
     }

    这个是之前的模板

    #include<cstdio>
    using namespace std;
    int n,p,a,b,m,x,y,ans;
    struct node
    {
        int l,r,w,f;
    }tree[400001];
    inline void build(int k,int ll,int rr)//建树 
    {
        tree[k].l=ll,tree[k].r=rr;
        if(tree[k].l==tree[k].r)
        {
            scanf("%d",&tree[k].w);
            return;
        }
        int m=(ll+rr)/2;
        build(k*2,ll,m);
        build(k*2+1,m+1,rr);
        tree[k].w=tree[k*2].w+tree[k*2+1].w;
    }
    inline void down(int k)//标记下传 
    {
        tree[k*2].f+=tree[k].f;
        tree[k*2+1].f+=tree[k].f;
        tree[k*2].w+=tree[k].f*(tree[k*2].r-tree[k*2].l+1);
        tree[k*2+1].w+=tree[k].f*(tree[k*2+1].r-tree[k*2+1].l+1);
        tree[k].f=0;
    }
    inline void ask_point(int k)//单点查询
    {
        if(tree[k].l==tree[k].r)
        {
            ans=tree[k].w;
            return ;
        }
        if(tree[k].f) down(k);
        int m=(tree[k].l+tree[k].r)/2;
        if(x<=m) ask_point(k*2);
        else ask_point(k*2+1);
    }
    inline void change_point(int k)//单点修改 
    {
        if(tree[k].l==tree[k].r)
        {
            tree[k].w+=y;
            return;
        }
        if(tree[k].f) down(k);
        int m=(tree[k].l+tree[k].r)/2;
        if(x<=m) change_point(k*2);
        else change_point(k*2+1);
        tree[k].w=tree[k*2].w+tree[k*2+1].w; 
    }
    inline void ask_interval(int k)//区间查询 
    {
        if(tree[k].l>=a&&tree[k].r<=b) 
        {
            ans+=tree[k].w;
            return;
        }
        if(tree[k].f) down(k);
        int m=(tree[k].l+tree[k].r)/2;
        if(a<=m) ask_interval(k*2);
        if(b>m) ask_interval(k*2+1);
    }
    inline void change_interval(int k)//区间修改 
    {
        if(tree[k].l>=a&&tree[k].r<=b)
        {
            tree[k].w+=(tree[k].r-tree[k].l+1)*y;
            tree[k].f+=y;
            return;
        }
        if(tree[k].f) down(k);
        int m=(tree[k].l+tree[k].r)/2;
        if(a<=m) change_interval(k*2);
        if(b>m) change_interval(k*2+1);
        tree[k].w=tree[k*2].w+tree[k*2+1].w;
    }
    int main()
    {
        scanf("%d",&n);//n个节点 
        build(1,1,n);//建树 
        scanf("%d",&m);//m种操作 
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&p);
            ans=0;
            if(p==1)
            {
                scanf("%d",&x);
                ask_point(1);//单点查询,输出第x个数 
                printf("%d",ans);
            } 
            else if(p==2)
            {
                scanf("%d%d",&x,&y);
                change_point(1);//单点修改 
            }
            else if(p==3)
            {
                scanf("%d%d",&a,&b);//区间查询 
                ask_interval(1);
                printf("%d
    ",ans);
            }
            else
            {
                 scanf("%d%d%d",&a,&b,&y);//区间修改 
                 change_interval(1);
            }
        }
    }
  • 相关阅读:
    nginx
    mysql
    intelij maven
    redis命令大全
    绑定touch事件后click无效,vue项目解决棒法
    新的用法
    img
    vuedragable
    自己总结
    vuex的项目在id中不能运行
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/10532993.html
Copyright © 2011-2022 走看看