点分治

点分治

简介:

点分治,顾名思义就是基于树上的节点进行分治。
实质就是将一棵树根据合理的分治方法(即改进复杂度),分成若干个子树,化成子问题。

常规操作:
这里要找的分治点即为重心。
根据重心进行划分子树,可以达到log。(具体证明不太想赘述,实则蒟蒻不会证...

模板(code):

int n;
vector<int>E[N];
int sz[N],F[N];
bool vis[N];
int root,size;

void getroot(int x,int f){
    sz[x]=1;
    F[x]=0;
    SREP(i,0,E[x].size()){
        int y=E[x][i];
        if(y==f || vis[y])continue;
        getroot(y,x);
        sz[x]+=sz[y];
        chkmax(F[x],sz[y]);
    }
    chkmax(F[x],size-sz[x]);
    if(F[x]<F[root])root=x;
}

void getdeep(int x,int f,/*dep,w,cost,v...*/){
    //统计,记录链的信息
    SREP(i,0,E[x].size()){
        int y=E[x][i];
        if(y==f || vis[y])continue;
        getdeep(y,x,/*加上该点的信息*/);
    }
}

int calc(int x,/*链上需要的信息*/){
    int res=0;
    getdeep(x,0,/**/);
    /*
    对刚刚得到这条链的信息具体操作
    一般就是按照一定的顺序遍历链,也可能是统计对某个的贡献... 
    */
    return res;
} 

void solve(int x){
    vis[x]=1;
    ans+=calc(x,/*一般初值为0*/);
    SREP(i,0,E[x].size()){
        int y=E[x][i];
        if(vis[y])continue;
        ans-=calc(y,/*该点的信息,容斥,清除y->x的非法答案*/);
        root=0;size=sz[y];
        getroot(y,0);
        solve(root); 
    }
}

void Clear(){
    mcl(vis,0); 
    size=n;
    F[0]=n+1;
    root=0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值