省选_简单数据结构

省选_简单数据结构

简单复习一下各种小模版:

其实这里的代码都是没有编译过的,时间紧迫,大概能敲下来就过了.

至于一些调试问题和语法问题就省选赛场上自由发挥了.

 

目录:

1.动态树

2.树状数组

3.静态主席树

4.动态主席树

5.并查集

6.可并堆

7.区间线段树

8.树链剖分

 

1. 动态树

/动态树
namespace LCT{
    int ch[maxn][2];
    int tag[maxn],lazy[maxn]; 
    int sta[maxn]; 
    int sumv[maxn]; 
    int siz[maxn]; 
    int maxv[maxn],minv[maxn]; 
    int lson(int x){ return ch[x][0]; }
    int rson(int x){ return ch[x][1]; }    
    int get(int x) { return ch[f[x]][1] == x; }
    int isRoot(int x){ return !(ch[f[x]][1]==x||ch[f[x]][0]==x); }
    void addv(int x,int delta){
        sumv[x] += siz[x] * delta; 
        lazy[x] += delta;  
    }
    void rev(int x){
        tag[x] ^= 1; 
        if(tag[x])
            swap(ch[x][0],ch[x][1]),tag[x] = 0; 
    }
    void pushdown(int x){
        if(lazy[x]) {
            addv(lson(x),lazy[x]); 
            addv(rson(x),lazy[x]); 
            lazy[x] = 0; 
        }
        if(tag[x])rev(lson(x)),rev(rson(x)),tag[x] = 0; 
    }
    void pushup(int x){
        sumv[x] = sumv[lson(x)] + sumv[rson(x)] + val[x]; 
        siz[x] = siz[lson(x)] + siz[rson(x)] + 1;         
        maxv[x] = max(maxv[lson(x)],maxv[rson(x)]); 
        minv[x] = min(minv[son(x)],minv[rson(x)]); 
    }
    void rotate(int x){
        int old=f[x],oldf=f[old],which=get(x); 
        if(!isRoot(old)) ch[oldf][ch[oldf][1]==old] = x; 
        ch[old][which]=ch[x][which^1],f[ch[old][which]]=old; 
        ch[x][which^1] = old,f[old] = x,f[x] = oldf; 
        pushup(old),pushup(x); 
    }
    void splay(int x){
        int v=0,u=x; 
        sta[++v] = x; 
        while(!isRoot(u)) sta[++v] = f[u],u=f[u]; 
        while(v) pushdown(sta[v--]); 
        u=f[u]; 
        for(int fa;(fa=f[x])!=u;rotate(x)) 
            if(f[fa]!=u) rotate(get(fa)==get(x) ? fa: x); 
    }
    void Access(int x){
        for(int y=0;x;y=x,x=f[x]) 
            splay(x),ch[x][1]=y; 
    }
    void makeRoot(int x){
        Access(x),splay(x),rev(x); 
    }
    void link(int x,int y){
        makeRoot(x),f[x]=y;
    }
    //x为y的父亲
    void cut(int x,int y){
        makeRoot(x),Access(y),splay(y); 
        ch[y][0]=f[ch[y][0]]=0; 
        pushup(y); 
    }
};

 

2. 树状数组

namespace BIT{
    int n;
    int C[maxn]; 
    int lowbit(int t) { return t & (-t); }
    void update(int x,int delta){
        while(x <= n) {
            C[x] += delta; 
            x += lowbit(x); 
        } 
    }
    int query(int x){
        int sum=0; 
        while(x >= 0)  sum += C[x],x -= lowbit(x); 
        return sum; 
    }
}; 

 

3.主席树(静态)

namespace Chair_Tree1{
    int node_cnt; 
    int ls[maxn],rs[maxn]; 
    int sumv[maxn]; 
    void build(int l,int r,int &o){
        if(l>r) return; 
        o=++node_cnt; 
        if(l==r) return ; 
        int mid=(l+r)>>1;
        build(l,mid,ls[o]); 
        build(mid+1,r,rs[o]);  
    }
    int update(int l,int r,int k,int o){
        int oo=++node_cnt; 
        sumv[oo] = sumv[o] + 1; 
        ls[oo] = ls[o];
        rs[oo] = rs[o]; 
        if(l==r) return oo; 
        int mid=(l+r)>>1;
        if(k<=mid) ls[oo] = update(l,mid,k,ls[o]); 
        else rs[oo] = update(mid+1,r,k,rs[o]); 
        return oo; 
    }
    int query(int u,int v,int l,int r,int k){
        if(l==r) return l; 
        int mid=(l+r)>>1;
        int delta = sumv[ls[v]] - sumv[ls[u]]; 
        if(delta >= k) return query(ls[u],ls[v],l,mid,k); 
        else return query(rs[u],rs[v],mid+1,r,k-delta); 
    }
};  

 

4. 主席树2(修改)

namespace Chair_Tree2{
    struct Queries{
        int c,l,r,k; 
        Queries(int c=0,int l=0,int r=0,)
    }asks[maxn]; 
    int lson[maxn*10],rson[maxn*10],root[maxn];
    int temp[2][200],count[2],sumv[maxn*10]; 
    int cnt_Tree; 
    int lowbit(int t){ return t & (-t); }       
    void insert(int l,int r,int pos,int delta,int &o){
        if(!o) o=++cnt_Tree; 
        sumv[o] += delta; 
        if(l==r) return ; 
        int mid=(l+r)>>1;
        if(pos<=mid)
            insert(l,mid,pos,delta,lson[o]); 
        else 
            insert(mid+1,r,pos,delta,rson[o]);
    }
    void update(int pos,int val,int delta){
        for(int i=pos;i<=n;i+=lowbit(i)) 
            insert(1,n,val,delta,root[i]); 
    }
    int query(int l,int r,int k){
        if(l==r) return l; 
        int sum=0; 
        for(int i=1;i<=count[0];++i) sum+=sumv[lson[temp[0][i]]];
        for(int i=1;i<=count[1];++i) sum-=sumv[lson[temp[1][i]]]; 
        int mid=(l+r)>>1;
        if(k<=sum){
            for(int i=1;i<=count[0];++i) temp[0][i]=lson[temp[0][i]]; 
            for(int i=1;i<=count[1];++i) temp[1][i]=lson[temp[1][i]]; 
            return query(l,mid,k); 
        }
        else {
            for(int i=1;i<=count[0];++i) temp[0][i]=rson[temp[0][i]];
            for(int i=1;i<=count[1];++i) temp[1][i]=rson[temp[1][i]]; 
            return query(mid+1,r,k-sum); 
        }
    }
    int Query(int l,int r,int k){
        memset(temp,0,sizeof(temp)); 
        count[0]=count[1]=0; 
        for(int i=r;i>=1;i-=lowbit(i)) 
            temp[0][++count[0]] = root[i]; 
        for(int i=l-1;i>=1;i-=lowbit(i)) 
            temp[1][++count[0]] = root[i]; 
        return query(1,n,k); 
    }
}; 

 

5.并查集

namespace Union_Find{
    int n; 
    int p[maxn]; 
    void init(){
        for(int i=1;i<=n;++i) p[i]=i;  
    }
    int find(int x){
        return p[x]==x?x:p[x] = find(p[x]); 
    }
    void merge(int a,int b){
        int x=find(a),y=find(b); 
        if(x==y) return; 
        p[x] = y; 
    }
};     

 

6.可并堆

namespace M_heap{
    int val[maxn]; 
    int ch[maxn][2]; 
    int dis[maxn]; 
    int siz[maxn]; 
    int merge(int a,int b){
        if(!a||!b) return a + b; 
        if(val[a] < val[b]) swap(a,b); 
        ch[a][1] = merge(ch[a][1],b); 
        if(dis[ch[a][1]]>dis[ch[a][0]])  swap(ch[a][0],ch[a][1]); 
        dis[a] = dis[ch[a][0]] + 1; 
        sumv[a] = sumv[ch[a][0]] + sumv[ch[a][1]] + val[a]; 
        siz[a] = siz[ch[a][0]] + siz[ch[a][1]] + 1;
        return a;  
    }
    void pop(int &a){
        int t=merge(ch[a][0],ch[a][1]); 
        siz[a] = sumv[a] = val[a] = ch[a][0] = ch[a][1] = 0; 
        a=t; 
    }
};    

 

7.线段树2(区间乘和区间加两个标记)

namespace Segment_Tree{ 
    #define ll long long  
    long long mod; 
    int val[maxn]; 
    ll sumv[maxn<<2],mult[maxn<<2],addv[maxn<<2]; 
    void pushdown(int o,int l,int r){
        int mid=(l+r)>>1,ls=(o<<1),rs=(o<<1)|1; 
        if(mult[o]!=1) {
            sumv[ls] = (sumv[ls] * mult[o])%mod;
            sumv[rs] = (sumv[rs] * mult[o])%mod; 
            mult[ls] = (mult[ls] * mult[o])%mod; 
            mult[rs] = (mult[rs] * mult[o])%mod; 
            addv[ls] = (addv[ls] * mult[o])%mod; 
            addv[rs] = (addv[rs] * mult[o])%mod; 
            mult[o] = 1; 
        }
        if(addv[o] != 0) {
            if(mid>=l) sumv[ls] += (mid-l+1) *addv[o]; 
            if(mid+1<=r) sumv[rs] += (r-mid) * addv[o]; 
            addv[ls] += addv[o],addv[rs] += addv[o]; 
            addv[o]=0; 
        }
    }
    void build_Tree(int l,int r,int o){
        if(l>r) return; 
        mult[o]=1;
        if(l==r) {
            sumv[o] = val[l]%mod; 
            return; 
        }
        int mid=(l+r)>>1,ls=(o<<1),rs=(o<<1)|1; 
        build_Tree(l,mid,ls); 
        build_Tree(mid+1,r,rs); 
        sumv[o] = (sumv[ls] + sumv[rs])%mod; 
    }
    void update_mult(int l,int r,int o,int L,int R,int delta){
        if(l > r || r < L || l > R) return; 
        if(l>=L&&r<=R) {
            sumv[o]*=delta; 
            mult[o]*=delta;
            addv[o]*=delta; 
            return; 
        }
        int mid=(l+r)>>1;
        pushdown(o,l,r); 
        update_mult(l,mid,(o<<1),L,R,delta); 
        update_mult(mid+1,r,(o<<1)|1,L,R,delta); 
        sumv[o] = sumv[(o<<1)] + sumv[(o<<1)|1]; 
    }
    void update_add(int l,int r,int o,int L,int R,int delta) {
        if(l > r || r < L || l > R) return; 
        if(l>=L&&r<=R){
            sumv[o]+=delta*(r-l+1);   
            addv[o]+=delta; 
            return; 
        }
        int mid=(l+r)>>1;
        pushdown(o,l,r); 
        update_add(l,mid,(o<<1),L,R,delta); 
        update_add(mid+1,r,(o<<1)|1,L,R,delta);
        sumv[o] = sumv[(o<<1)] + sumv[(o<<1)|1]; 
    }
    int query(int l,int r,int o,int L,int R){
        if(l > r || r < L || l > R) return 0;      
        if(l >= L && r <= R) return sumv[o]; 
        int mid=(l+r)>>1; 
        pushdown(o,l,r); 
        return query(l,mid,(o<<1),L,R)+query(mid+1,r,(o<<1)|1,L,R); 
    }
}; 

  

 8.树链剖分

namespace Heavy_Edge{
    #define ll long long 
    #define lson (o<<1)
    #define rson (o<<1)|1
    ll mod;
    int n; 
    int head[maxn],nex[maxn<<1],to[maxn<<1]; 
    int p[maxn],son[maxn],dep[maxn],top[maxn]; 
    int cnt,cnt2; 
    ll sumv[maxn<<2]; 
    int lazy[maxn];
    int A[maxn],st[maxn],ed[maxn],val[maxn]; 
    void addedge(int u,int v){
        nex[++cnt]=head[u],head[u]=cnt,to[cnt]= v;
    }
    void dfs1(int u,int fa,int cur){
        p[u]=fa,dep[u]=cur,siz[u]=1; 
        for(int i=head[u];i;i=nex[i])
            if(to[i]!=fa) {
                dfs1(to[i],u,cur+1); 
                siz[u]+=siz[to[i]]; 
                if(son[u]==-1||siz[to[i]]>siz[son[u]]) 
                    son[u] = to[i]; 
            }
        
    }
    void dfs2(int u,int tp){
        top[u]=tp,A[u]=++cnt2,st[u]=cnt2; 
        if(son[u]!=-1) dfs2(son[u],tp); 
        for(int i=head[u];i;i=nex[i])
            if(to[i]!=p[u]&&to[i]!=son[u]) 
                dfs2(to[i],to[i]); 
        ed[u]=cnt2; 
    }
    void pushdown(int l,int r,int o){
        if(lazy[o]){
            int mid=(l+r)>>1;
            lazy[lson]+=lazy[o],lazy[rson]+=lazy[o]; 
            sumv[lson]+=(mid-l+1)*lazy[o]; 
            sumv[rson]+=(r-mid)*lazy[o]; 
            lazy[o]=0; 
        }
    }
    void build(int l,int r,int o,int arr[]){
        if(l>r) return; 
        if(l==r) {
            sumv[o]=arr[l];
            return; 
        }
        int mid=(l+r)>>1;
        build(l,mid,lson,arr); 
        build(mid+1,r,rson,arr); 
        sumv[o] = sumv[lson] + sumv[rson]; 
    }
    void update(int l,int r,int k,int L,int R,int o){
        if(l>r||r<L||l>R) return;
        if(l>=L&&r<=R){
            lazy[o]+=k;
            sumv[o]+=(r-l+1)*k;
            return; 
        }
        int mid=(l+r)>>1;
        pushdown(l,r,o); 
        update(l,mid,k,L,R,lson);
        update(mid+1,r,k,L,R,rson); 
        sumv[o] = sumv[lson] + sumv[rson]; 
    }
    long long query(int l,int r,int o,int L,int R){
        if(l>r||r<L||l>R) return 0; 
        if(l>=L&&r<=R) return sumv[o]; 
        int mid=(l+r)>>1;
        pushdown(l,r,o); 
        return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R); 
    }
    void up(int x,int y,int del){
        while(top[x]!=top[y]){
            if(dep[top[x]>dep[top[y]]) swap(x,y); 
            update(1,n,del,A[top[y]],A[y],1); 
        }
        if(dep[x]<dep[y]) swap(x,y); 
        update(1,n,del,A[y],A[x],1); 
    }
    long long look_up(int x,int y){
        long long sum=0;
        while(top[x]!=top[y]) {
            if(dep[top[x]]>dep[top[y]]) swap(x,y); 
            sum+=query(1,n,1,A[top[y]],A[y]); 
            y=p[top[y]]; 
        }
        if(dep[y]>dep[x]) swap(x,y); 
        sum+=query(1,n,1,A[y],A[x];     
        return sum; 
    }
};   

  

posted @ 2019-04-04 16:14 EM-LGH 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值