夏吉巴乱搞按链分块的块状树

Posted caturra

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了夏吉巴乱搞按链分块的块状树相关的知识,希望对你有一定的参考价值。

我感觉可以开\(O(\sqrt{n})\)棵01字典树来做省赛C题
目前处于测试阶段

#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
using namespace std;
const int MAXN = 1e5+11;
typedef long long ll;
ll read(){
    ll x=0,f=1;register char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],head[MAXN<<1],tot;
int val[MAXN],depth[MAXN],belong[MAXN];
void init(){
    memset(head,-1,sizeof head);
    tot=0;
}
void add(int u,int v){
    to[tot]=v;
    nxt[tot]=head[u];
    head[u]=tot++;
}
struct BLOCK{
    int block[3003][3003],size[3003],cnt,limit;
    int _from[6006],_to[6006],_nxt[6006],_head[3003],_tot;
    void _add(int u,int v){
        _to[_tot]=v;
        _from[_tot]=u;
        _nxt[_tot]=_head[u];
        _head[u]=_tot++;
    }
    void init(int lmt){
        size[0]=cnt=_tot=0;
        limit=lmt;
        memset(_head,-1,sizeof _head);
    }
    void build(int u,int fa,int d){
        depth[u]=d;
        if(fa==-1){
            belong[u]=++cnt;
            block[cnt][++size[cnt]]=u;
        }else{
            int id=belong[fa];
            int tail=block[id][size[id]];
            if(tail==fa&&size[id]<=limit){
                belong[u]=id;
                block[id][++size[id]]=u;
            }else{
                belong[u]=++cnt;
                block[cnt][++size[cnt]]=u;
                _add(cnt,belong[fa]);
            }
        }
        erep(i,u){
            int v=to[i];
            if(v==fa) continue;
            build(v,u,d+1);
        }
    }
    void out(int n){
        rep(i,1,n){
            cout<<"id: "<<i<<" blockID: "<<belong[i]<<" size: "<<size[belong[i]]<<endl;
        }
        cout<<endl;
        //for(int i=_head[1]; ~i; i=_nxt[i]){
            //int v=_to[i];
            //cout<<_from[i]<<"-->"<<_to[i]<<endl;
        //}
    }
}b;

int main(){
    int n;
    while(cin>>n){
        init();
        rep(i,1,n-1){
            int u=read();
            int v=read();
            add(u,v);
            add(v,u);
        }
        // rep(i,1,n) val[i]=read();
        b.init(sqrt(n)+1);
        b.build(1,-1,1);
        b.out(n);
    }
}

/*
15
1 2
2 3
3 4
2 5
1 6
6 7
7 8
8 9
9 13
13 15
13 14
8 10
10 11
11 12
*/

改良版

#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
using namespace std;
const int MAXN = 1e5+11;
typedef long long ll;
ll read(){
    ll x=0,f=1;register char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],head[MAXN<<1],tot;
int val[MAXN],depth[MAXN],belong[MAXN],treesize[MAXN],son[MAXN];
void init(){
    memset(head,-1,sizeof head);
    tot=0;
}
void add(int u,int v){
    to[tot]=v;
    nxt[tot]=head[u];
    head[u]=tot++;
}
struct BLOCK{
    vector<int> block[MAXN];
    // int block[3003][3003],size[3003],
    int cnt,limit;
    int _from[MAXN],_to[MAXN],_nxt[MAXN],_head[MAXN],_tot;
    void _add(int u,int v){
        _to[_tot]=v;
        _from[_tot]=u;
        _nxt[_tot]=_head[u];
        _head[u]=_tot++;
    }
    void init(int lmt,int n){
        rep(i,1,n) block[i].clear();
        cnt=_tot=0;
        limit=lmt;
        memset(_head,-1,sizeof _head);
    }
    void prepare(int u,int fa,int d){
        depth[u]=d; treesize[u]=1; son[u]=-1;
        erep(i,u){
            int v=to[i];
            if(v==fa) continue;
            prepare(v,u,d+1);
            treesize[u]+=treesize[v];
            if(son[u]==-1||treesize[v]>treesize[son[u]]) son[u]=v;
        }
    }
    void build(int u,int fa){
        if(fa==-1){
            belong[u]=++cnt;
            block[cnt].push_back(u);
        }else{
            int id=belong[fa];
            int sz=block[id].size();
            int tail=block[id][sz-1];
            if(tail==fa&&sz<=limit&&son[fa]==u){
                belong[u]=id;
                block[id].push_back(u);
            }else{
                belong[u]=++cnt;
                block[cnt].push_back(u);
                _add(cnt,belong[fa]);
            }
        }
        erep(i,u){
            int v=to[i];
            if(v==fa) continue;
            build(v,u);
        }
    }
    void build(int root){
        prepare(root,-1,1);
        build(root,-1);
    }
    void out(int n){
        rep(i,1,n){
            cout<<"id: "<<i<<" blockID: "<<belong[i]<<" size: "<<block[belong[i]].size()<<endl;
        }
        cout<<endl;
        for(int i=_head[5]; ~i; i=_nxt[i]){
            int v=_to[i];
            cout<<_from[i]<<"-->"<<_to[i]<<endl;
        }
    }
}b;
int main(){
    int n;
    while(cin>>n){
        init();
        rep(i,1,n-1){
            int u=read();
            int v=read();
            add(u,v);
            add(v,u);
        }
        // rep(i,1,n) val[i]=read();
        b.init(sqrt(n)+1,n);
        b.build(1);
        b.out(n);
    }
}

以上是关于夏吉巴乱搞按链分块的块状树的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3720 gty的妹子树

块状数组

待学习内容

分块,莫队,BSGS,块状链表

LOJ.6282.数列分块入门6(块状链表/分块)

bzoj3744Gty的妹子序列 分块+树状数组+主席树