1. 程式人生 > >【夏吉巴亂搞】按鏈分塊的塊狀樹

【夏吉巴亂搞】按鏈分塊的塊狀樹

etc set its main ack cout 亂搞 print fine

我感覺可以開\(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);
    }
}

【夏吉巴亂搞】按鏈分塊的塊狀樹