zoukankan      html  css  js  c++  java
  • 数据结构模板合集

    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;
    
  • 相关阅读:
    ORM查询相关的操作
    分享一些珍藏和网上搜集的一些接码平台
    DRF: serializers ModelSerializer的序列化中model在有外键的情况下显示name代替显示id的几种方式
    Django Rest framework中序列化A表时怎么获取B表的数据
    10步入门Django Rest framework后端接口框架
    Django Rest framework后端接口框架,常用的子类视图
    redis学习(九)——数据持久化
    Java8之lambda表达式
    Java多线程(九)—— interrupt()和线程终止方式
    redis学习(八)——redis应用场景
  • 原文地址:https://www.cnblogs.com/hzf29721/p/10070671.html
Copyright © 2011-2022 走看看