数据结构模板合集

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;
posted @ 2018-12-05 14:16  hzf29721  阅读(553)  评论(1编辑  收藏  举报