Skip to content
hotman edited this page Oct 25, 2020 · 3 revisions

segment tree

#pragma once
#include<vector>
#include"../alga/maybe.hpp"

/**
 * @brief セグメント木
 * @see https://en.wikipedia.org/wiki/Segment_tree
 */

template<typename T,typename F>
class segment_tree{
	maybe<T>* node;
    F op;
	int n=1;
	public:
    segment_tree(){}
	segment_tree(int sz,F op=F()):op(op){
		while(n<=sz)n<<=1;
		node=new maybe<T>[n*2];
		for(int i=0;i<n*2;i++)node[i]=maybe<T>();
	}
    segment_tree(const std::vector<T>&v,F op=F()):op(op){
        auto f=expand<T,F>(op);
        const int sz=v.size();
		while(n<=sz)n<<=1;
		node=new maybe<T>[n*2]();
        for(int i=0;i<sz;i++)node[i+n]=maybe<T>(v[i]);
        for(int i=n-1;i>=1;i--)node[i]=f(node[i*2],node[i*2+1]);
	}
    maybe<T> get(int l,int r){
        auto f=expand<T,F>(op);
        l+=n;r+=n;
        maybe<T> s,t;
        while(l<r){
            if(l&1)s=f(s,node[l++]);
            if(r&1)t=f(node[--r],t);
            l>>=1;r>>=1;
        }
        return f(s,t);
    }
    void apply(int t,T _val){
        auto f=expand<T,F>(op);
        t+=n;
        maybe<T> val=maybe<T>(_val);
        while(t){
            node[t]=f(node[t],val);
            t=t>>1;
        }
    }
    void apply_left(int t,T _val){
        auto f=expand<T,F>(op);
        t+=n;
        maybe<T> val=maybe<T>(_val);
        while(t){
            node[t]=f(val,node[t]);
            t=t>>1;
        }
    }
    void change(int t,T val){
        auto f=expand<T,F>(op);
        t+=n;
        node[t]=maybe<T>(val);
        while(t>1){
            t=t>>1;
            node[t]=f(node[t*2],node[t*2+1]);
        }
    }
};

dual segment tree

#pragma once
#include"../alga/maybe.hpp"

/**
 * @brief 双対セグメント木
 */

template<typename T,typename F>
class dual_segment_tree{
	struct node;
	using np=node*;
	using i64=long long;
	struct node{
		maybe<T> val;
		np ch[2]={nullptr,nullptr};
		node(maybe<T> val=maybe<T>()):val(val){}
	};
	np root=nullptr;
	i64 n=1,sz;
    F op;
	public:
	dual_segment_tree(i64 sz,F op=F()):sz(sz),op(op){while(n<sz)n<<=1;}
	inline void update(i64 l,i64 r,T x){update(l,r,x,0,n,root);}
	inline maybe<T> get(i64 x){return get(x,0,n,root);}
	private:
	void eval(np& t){
        auto f=expand<T,F>(op);
		if(t->val.is_none())return;
		if(!t->ch[0])t->ch[0]=new node();
		if(!t->ch[1])t->ch[1]=new node();
		t->ch[0]->val=f(t->ch[0]->val,t->val);
		t->ch[1]->val=f(t->ch[1]->val,t->val);
		t->val=maybe<T>();
	}
	void update(i64 a,i64 b,T x,i64 l,i64 r,np& t){
        auto f=expand<T,F>(op);
        if(!t)t=new node();
		if(r-l>1)eval(t);
		if(r<=a||b<=l)return;
		else if(a<=l&&r<=b)t->val=f(t->val,x);
	    else if(r-l>1){
			update(a,b,x,l,(l+r)/2,t->ch[0]);
			update(a,b,x,(l+r)/2,r,t->ch[1]);
		}
	}
	maybe<T> get(i64 x,i64 l,i64 r,np& t){
        auto f=expand<T,F>(op);
        if(!t)t=new node();
		if(r-l>1)eval(t);
		if(x<l||r<=x)return maybe<T>();
        else if(r-l==1){
            return t->val;
        }
		else return f(get(x,l,(l+r)/2,t->ch[0]),get(x,(l+r)/2,r,t->ch[1]));
	}
};

lazy segment tree

#pragma once
#include"../alga/maybe.hpp"

template<typename T,typename E,typename F,typename G,typename H>
class lazy_segment_tree{
    using i64=long long;
    i64 n;
    i64 sz;
    struct node;
    using np=node*;
    struct node{
        maybe<T> val=maybe<T>();
        maybe<E> lazy=maybe<E>();
        np lch=nullptr,rch=nullptr;
        node(){}
    };
    np root=new node();
    maybe<T> update(i64 a,i64 b,E x,i64 l,i64 r,np t){
        auto f=expand<T,F>(_f);
        eval(t,l,r);
        //区間外
        if(r<=a||b<=l)return t->val;
        //全部区間内
        if(a<=l&&r<=b){
            t->lazy=x;
            eval(t,l,r);
            return t->val;
        }
        //一部区間内
        return t->val=f(update(a,b,x,l,(l+r)/2,t->lch),update(a,b,x,(l+r)/2,r,t->rch));
    }
    maybe<T> get(i64 a,i64 b,i64 l,i64 r,np t){
        auto f=expand<T,F>(_f);
        eval(t,l,r);
        //区間外
        if(r<=a||b<=l)return maybe<T>();
        //全部区間内
        if(a<=l&&r<=b)return t->val;
        //一部区間内
        return f(get(a,b,l,(l+r)/2,t->lch),get(a,b,(l+r)/2,r,t->rch));
    }
    void eval(np t,i64 l,i64 r){
        auto g=expand<E,G>(_g);
        if(r-l>1){
            if(!t->lch)t->lch=new node();
            if(!t->rch)t->rch=new node();
            t->lch->lazy=g(t->lch->lazy,t->lazy);
            t->rch->lazy=g(t->rch->lazy,t->lazy);
        }
        t->val=h(t->val,t->lazy,l,r);
        t->lazy=maybe<E>();
    }
    F _f;G _g;H _h;
    maybe<T> h(const maybe<T>&s,const maybe<E>&t,int l,int r){
        if(t.is_none())return s;
        else return maybe<T>(_h(s,t.unwrap(),l,r));
    }
    public:
    lazy_segment_tree(i64 sz,F f=F(),G g=G(),H h=H()):n(1),sz(sz),_f(f),_g(g),_h(h){while(n<sz)n<<=1;}
    //0-indexed [a,b)
    void update(i64 a,i64 b,E x){update(a,b,x,0,n,root);}
    //0-indexed [a,b)
    maybe<T> get(i64 a,i64 b){return get(a,b,0,n,root);}
};

UF

/**
 * @brief Union Find
 * @see https://ja.wikipedia.org/wiki/%E7%B4%A0%E9%9B%86%E5%90%88%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0
 */

class UF{
    public:
    vector<int> data;
    int sz;
	public:
    UF(int sz):sz(sz){data.resize(sz,-1);}
    bool unite(int x,int y){
        x=root(x);y=root(y);
        if(x==y)return 0;
        if(data[x]>data[y])swap(x,y);
		data[x]+=data[y];
		data[y]=x;
		sz--;
        return 1;
    }
    inline int root(int x){return data[x]<0?x:data[x]=root(data[x]);}
    inline bool same(int x, int y){return root(x)==root(y);}
    inline int size(){return sz;}
	inline int size(int x){return -data[root(x)];}
};

UF_min

#pragma once
#include<vector>
#include<numeric>
#include<limits>

/**
 * @brief 根とのPathの中での最小値を返すUnionFind
 */

template<typename T>
struct uf_min{
    constexpr static int inf=std::numeric_limits<T>::max();
    std::vector<int>par,mnid;
    std::vector<T>mn;
    uf_min(int v){
        par.resize(v);
        mn.resize(v,inf);
        mnid.resize(v);
        std::iota(par.begin(),par.end(),0);
        std::iota(mnid.begin(),mnid.end(),0);
    }
    int find(int v){
        if(par[v]==v)return v;
        int r=find(par[v]);
        if(mn[v]>mn[par[v]]){
            mnid[v]=mnid[par[v]];
            mn[v]=mn[par[v]];
        }
        par[v]=r;
        return r;
    }
    void set(int v,T x){
        mn[v]=x;
    }
    T eval(int v){
        find(v);
        return mnid[v];
    }
    //xをyの親にする
    void link(int x,int y){
        par[y]=x;
    }
};

UF_list

class UF{
    public:
    vector<int> data;
    int sz;
	public:
    UF(int sz):sz(sz){
        for(int i=0;i<sz;++i)data[i]=i;
    }
    bool unite(int x,int y){
        data.swap(x,y);
        return 1;
    }
};

UF_data

template<typename T,typename F>
class UF_data{
    public:
    vector<int> data;
    vector<T>val;
    int sz;
    F merge;
	public:
    UF_data(int sz,F merge=F()):sz(sz),merge(merge){data.resize(sz,-1);val.resize(sz,T());}
    bool unite(int x,int y){
        x=root(x);y=root(y);
        if(x==y)return 0;
        if(data[x]>data[y])swap(x,y);
		data[x]+=data[y];
		data[y]=x;
        val[x]=merge(move(val[x]),move(val[y]));
		sz--;
        return 1;
    }
    inline void set(int x,const T&v){
        x=root(x);
        val[x]=v;
    }
    inline T get(int x){
        return val[root(x)];
    }
    inline int root(int x){return data[x]<0?x:data[x]=root(data[x]);}
    inline bool same(int x, int y){return root(x)==root(y);}
    inline int size(){return sz;}
	inline int size(int x){return -data[root(x)];}
};

BIT

#pragma once
#include<vector>

/**
 * @brief BinaryIndexedTree
 */

struct BIT{
    std::vector<long long> bit;
    int n;
    BIT(long long n):n(n){
        bit.resize(n+1,0);
    }
    //0-indexed [0,x)-sum
    long long sum(long long x){
        long long res=0;
        for(int i=x;i;i-=i&-i)res+=bit[i];
        return res;
    }
    //0-indexed [x,y)-sum
    long long sum(long long x,long long y){
        return sum(y)-sum(x);
    }
    //0-indexed
    void add(long long x,long long val){
        if(x>=n)return;
        for(long long i=x+1;i<=n;i+=i&-i)bit[i]+=val;
    }
};

#bit vector

#pragma once

/**
 * @brief BitVector
 */

class bitvec{
	using u32=unsigned int;
	using u8=unsigned char;
    using lint=long long;
	//4*10^6対応
	//ブロック幅8,チャンク幅256
	const int bw=8,cw=256;
	const int len=15625,sz=4000000;
	bool data[4000000]={0};
	u32 chunk[15626];
	u8 block[15625][33];
	public:
	bitvec(){}
	void build(){
		chunk[0]=0;
		for(int i=0;i<15625;i++){
			block[i][0]=0;
			for(int j=0;j<31;j++){
				block[i][j+1]=block[i][j];
				for(int k=0;k<8;k++)block[i][j+1]+=data[i*cw+j*bw+k];
			}
			chunk[i+1]=chunk[i]+block[i][31];
			for(int k=0;k<8;k++)chunk[i+1]+=data[i*cw+31*bw+k];
		}
	}
	inline void set(int idx,bool b){data[idx]=b;}
	inline bool get(int idx){return data[idx];}
    inline int rank(int idx,bool b)const{
        if(b)return rank1(idx);
        else return idx-rank1(idx);
	}
	inline int rank1(int idx)const{
		int a=idx/cw,b=idx%cw/bw,c=idx%bw;
		int res=chunk[a]+block[a][b];
		for(int i=1;i<c+1;i++)res+=data[idx-i];
		return res;
	}
	inline int select(int num){
		if (num==0)return 0;
        if (rank1(sz)<num)return -1;
        int ok=sz,ng=0;
		while (ok-ng>1) {
			int mid=(ok+ng)/2;
			if (rank1(mid)>=num)ok =mid;
			else ng=mid;
		}
		return ok;
	}
};
Clone this wiki locally