数据结构模板合集

1、线段树

线段树Lazy操作模板(区间修改,区间查询)
class Segment_Tree_Lazy{
    private:
    #define ls (p<<1)
    #define rs ((p<<1)|1)
    #define mid ((l+r)>>1)
    int val[100010],cnt[100010];
    inline void updata(int p){
        val[p]=val[ls]+val[rs];
    }
    inline void add(int p,int v,int t){
        val[p]+=v*t;
        cnt[p]+=v;
    }
    inline void pushdown(int p,int l,int r){
        if(!cnt[p])
            return ;
        add(ls,cnt[p],mid-l+1);
        add(rs,cnt[p],r-mid);
        cnt[p]=0;
    }
    public:
    inline void build_tree(int p,int l,int r){
        cnt[p]=0;
        if(l==r){
            val[p]=a[l];
            return ;
        }
        build_tree(ls,l,mid);
        build_tree(rs,mid+1,r);
        updata(p);
    }
    inline void change(int p,int l,int r,int x,int y,int t){
        if(x<=l&&r<=y){
            add(p,t,r-l+1);
            return ;
        }
        pushdown(p,l,r);
        if(x<=mid)
            change(ls,l,mid,x,y,t);
        if(y>mid)
            change(rs,mid+1,r,x,y,t);
        updata(p);
    }
    inline int ask(int p,int l,int r,int x,int y){
        if(x<=l&&r<=y)
            return val[p];
        int ans=0;
        pushdown(p,l,r);
        if(x<=mid)
            ans+=ask(ls,l,mid,x,y);
        if(y>mid)
            ans+=ask(rs,mid+1,r,x,y);
        return ans;
    }
}S;
二维线段树模板(单点修改,区间查询)
class Segment_Tree_xy{
    private:
    #define ls(p) (p<<1)
    #define rs(p) ((p<<1)|1)
    #define mid ((l+r)>>1)
    int tree[5000][5000];
    inline void updata(int px,int py){
        tree[px][py]=tree[px][ls(py)]+tree[px][rs(py)];
    }
    public:
    inline void change_y(int py,int l,int r,int y,int t,int px){
        if(l==r){
            tree[px][py]+=t;
            return ;
        }
        if(y<=mid)
            change_y(ls(py),l,mid,y,t,px);
        if(y>mid)
            change_y(rs(py),mid+1,r,y,t,px);
        updata(px,py);
    }
    inline void change_x(int px,int l,int r,int x,int y,int t){
        if(l==r){
            change_y(1,1,n,y,t,px);
            return ;
        }
        if(x<=mid)
            change_x(ls(px),l,mid,x,y,t);
        if(x>mid)
            change_x(rs(px),mid+1,r,x,y,t);
        change_y(1,1,n,y,t,px);
    }
    inline int ask_y(int py,int l,int r,int  y1,int y2,int px){
        if(y1<=l&&r<=y2)
            return tree[px][py];
        int ans=0;
        if(y1<=mid)
            ans+=ask_y(ls(py),l,mid,y1,y2,px);
        if(y2>mid)
            ans+=ask_y(rs(py),mid+1,r,y1,y2,px);
        return ans;
    }
    inline int ask_x(int px,int l,int r,int x1,int y1,int x2,int y2){
        if(x1<=l&&r<=x2)
            return ask_y(1,1,n,y1,y2,px);
        int ans=0;
        if(x1<=mid)
            ans+=ask_x(ls(px),l,mid,x1,y1,x2,y2);
        if(x2>mid)
            ans+=ask_x(rs(px),mid+1,r,x1,y1,x2,y2);
        return ans;
    }
}S;
线段树标记永久化模板(标记不下传,主要用于李超线段树与主席树等)
class Tag_Forever_Segment_Tree{
    public:
    #define ls (p<<1)
    #define rs ((p<<1)|1)
    #define mid ((l+r)>>1)
    int val[100010],tag[100010];
    inline void updata(int p){
        val[p]=val[ls]+val[rs];
    }
    inline void build_tree(int p,int l,int r){
        if(l==r){
            val[p]=a[l];
            return ;
        }
        build_tree(ls,l,mid);
        build_tree(rs,mid+1,r);
        updata(p);
    }
    inline void change(int p,int l,int r,int x,int y,int t){
        val[p]+=(y-x+1)*t;
        if(x<=l&&r<=y){
            tag[p]+=t;
            return ;
        }
        if(y<=mid)
            change(ls,l,mid,x,y,t);
        if(x>mid)
            change(rs,mid+1,r,x,y,t);
        if(y>mid&&x<=mid){
            change(ls,l,mid,x,mid,t);
            change(rs,mid+1,r,mid+1,y,t);
        }
    }
    inline int ask(int p,int l,int r,int x,int y,int sum){
        if(l==r)
            return sum+val[p];
        if(y<=mid)
            return ask(ls,l,mid,x,y,sum+tag[p]);
        if(x>mid)
            return ask(rs,mid+1,r,x,y,sum+tag[p]);
        if(y>mid&&x<=mid){
            return ask(ls,l,mid,x,mid,sum+tag[p])+ask(rs,mid+1,r,mid+1,y,sum+tag[p]);
        }
    }
}T;
线段树合并模板
class Mergable_Segment{
    public:
    #define mid ((l+r)>>1)
    int val[100010],ls[100010],rs[100010],pnt_num;
    inline void updata(int p){
        val[p]=val[ls[p]]+val[rs[p]];
    }
    public:
    inline void change(int &p,int l,int r,int x){
        if(!p)
            p=++pnt_num;
        if(l==r){
            val[p]=1;
            return ;
        }
        if(x<=mid)
            change(ls[p],l,mid,x);
        else
            change(rs[p],mid+1,r,x);
        updata(p);
    }
    inline int query(int p,int l,int r,int x){
        if(x>val[p])
            return 0;
        if(l==r)
            return l;
        if(val[ls[p]]>=x)
            return query(ls[p],l,mid,x);
        else
            return query(rs[p],mid+1,r,x-val[ls[p]]);
    }
    inline int merge(int a,int b){
        if(!a||!b)
            return a+b;
        ls[a]=merge(ls[a],ls[b]);
        rs[a]=merge(rs[a],rs[b]);
        updata(a);
        return a;
    }
}M;
主席树模板(可持久化线段树,可访问历史版本,详见 浅谈可持久化线段树(主席树))
class Persistable_Segment_Tree{
    private:
    #define mid ((l+r)>>1)
    int pntnum,ls[20000010],rs[20000010],tree[20000010];
    //ls[i]为i的左儿子,rs[i]为i的右儿子,tree[i]为i的值
    public:
    inline void clear(){//清空操作 
        pntnum=0;//节点数置为0 
        mem(tree,0);mem(ls,0);mem(rs,0);//清空数组 
    }
    inline void build_tree(int &pos,int l,int r){
        pos=++pntnum;//添加新节点,当前节点编号为++pntnum
        if(l==r){
            tree[pos]=val[l];//初始化每个叶节点的值
            return ;
        }
        build_tree(ls[pos],l,mid);
        build_tree(rs[pos],mid+1,r); 
    }
    inline void change(int &pos,int vsn,int l,int r,int loc,int val){//pos新版本的当前节点编号,vsn旧版本的当前节点编号,l左端点,r右端点,loc要修改的节点编号,val修改值
        pos=++pntnum;//新建节点
        if(l==r){
            tree[pos]=val;//修改值
            return ;
        }
        ls[pos]=ls[vsn];//继承旧版本左子树
        rs[pos]=rs[vsn];//继承旧版右左子树
        if(loc<=mid)//如果要修改的节点在左子树中
            change(ls[pos],ls[vsn],l,mid,loc,val);//处理左子树
        else
            change(rs[pos],rs[vsn],mid+1,r,loc,val);//处理右子树
    }
    inline int ask(int vsn,int l,int r,int loc){//vsn要访问的版本的当前节点编号,l左端点,r右端点,loc要访问的节点编号
        if(l==r)
            return tree[vsn];
        if(loc<=mid)//如果在左子树中
            return ask(ls[vsn],l,mid,loc);
        else
            return ask(rs[vsn],mid+1,r,loc);
    }
}P;

转载于:https://www.cnblogs.com/hzf29721/p/10070671.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++中的数据结构模板是一种通用的数据结构定义方式,可以根据不同的数据类型来创建具体的数据结构对象。通过使用类模板,可以实现对不同类型数据的操作和管理。 在C++中,可以使用类模板来定义各种数据结构,如链表、栈、队列、二叉树等。类模板的定义使用关键字template,后面跟着模板参数列表,其中可以包含类型参数和非类型参数。类型参数用于指定数据类型,非类型参数用于指定一些常量值。 下面是一个简单的示例,展示了如何使用类模板定义一个链表: ```cpp template <typename T> class LinkedList { private: struct Node { T data; Node* next; }; Node* head; public: LinkedList() : head(nullptr) {} void insert(const T& value) { Node* newNode = new Node; newNode->data = value; newNode->next = nullptr; if (head == nullptr) { head = newNode; } else { Node* current = head; while (current->next != nullptr) { current = current->next; } current->next = newNode; } } // 其他操作方法... }; ``` 在上面的示例中,`LinkedList` 是一个类模板,使用了类型参数 `T` 来表示链表中存储的数据类型。通过在类模板中定义一个内部结构体 `Node` 来表示链表节点,然后使用 `head` 指针来指向链表的头节点。 类模板中的成员函数可以像普通类一样进行定义和实现,可以根据具体的数据类型进行相应的操作。在上面的示例中,`insert` 函数用于向链表中插入新的节点。 使用类模板时,需要在创建对象时指定具体的数据类型,例如: ```cpp LinkedList<int> intList; // 创建一个存储整数的链表对象 intList.insert(10); intList.insert(20); ``` 这样就可以创建一个存储整数的链表对象,并向其中插入两个节点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值