hdu 5398 GCD Tree

来源:互联网 发布:snmp 设置端口状态 编辑:程序博客网 时间:2024/04/25 02:31

显然应当预处理出所有的答案,考虑在n1的最大生成树上加边得到n的最大生成树,即对每一条边uv,在链uv上找到值最小的边并删除,根据Kruskal的流程,这个操作得到的必然是一个更优的解。
考虑对于n的一个因数d,满足(a,n)=da必然为a=dp|(p,n)=1,设所有满足(ai,n)=daidp1,dp2...dpϕ(nd)。在最大生成树中,连接了所有dpi的分量上的所有边的权值都应当不小于d,因为如果有一条边小于d,考虑Kruskal流程,其连接的两个子树应当由(dpi,dpj)来连接((dpi,dpj)d)。也就是说,如果连接一条(n,dpi),并能够通过删除某边得到更优解,那么这个操作只能进行一次(第二次连接必然构成了一个边权皆不小于d的环)且任意dpi都是满足要求的(因为可删除的边在连接了所有dpi的分量的外面)。
所以每次枚举当前n的所有因数连边,之后让lct做一点微小的工作即可,复杂度O(nnlogn)

#include<algorithm>#include<iostream>#include<cstring>#include<climits>#include<cstdio>//--containerusing namespace std;#include<stack>typedef long long ll;const int up=1000000;//--#define clr(a) memset(a,0,sizeof(a))struct nd{nd* fa,* gfa,* cd[2];int mi,wg;bool fg;}ndr[300010],*id[100010];struct eg{int v,nx;}gp[1200000];ll rs[100010],ts=0;int n,tn,cnt,hd[100010];stack<nd*>sk;void psh(int u,int v){    ++cnt;gp[cnt].v=v;    gp[cnt].nx=hd[u],hd[u]=cnt;};nd* _new(){    nd* t;if(!sk.empty()){        t=sk.top();sk.pop();t->cd[0]=t->cd[1]=t->fa=t->gfa=0,t->fg=0;        return t;    };    ndr[tn].cd[0]=ndr[tn].cd[1]=ndr[tn].fa=ndr[tn].gfa=0,ndr[tn].fg=0;    return &ndr[tn++];};void _delete(nd* t){sk.push(t);};inline void mis(nd* v){    v->mi=min(v->wg,min(v->cd[0]?v->cd[0]->mi:up,v->cd[1]?v->cd[1]->mi:up));};void fgs(nd* v){    if(v->cd[0])v->cd[0]->fg^=1;    if(v->cd[1])v->cd[1]->fg^=1;    swap(v->cd[0],v->cd[1]),v->fg=0;};void tgs(nd* v){if(v->fa){tgs(v->fa);v->gfa=v->fa->gfa;}if(v->fg)fgs(v);};void rot(nd* v){    int i,j,d;nd* f=v->fa,* g=f->fa;d=f->cd[0]==v?0:1;    if(g)g->cd[g->cd[0]==f?0:1]=v;v->fa=g,f->fa=v;    if(v->cd[d^1])v->cd[d^1]->fa=f;f->cd[d]=v->cd[d^1],v->cd[d^1]=f;mis(f),mis(v);};void spy(nd* v,nd* x){    int i,j,a,b;nd* f,* g;for(tgs(v);v->fa!=x;){        f=v->fa,g=f->fa;        if(x==g){rot(v);break;};        a=f->cd[0]==v?0:1,b=g->cd[0]==f?0:1;        if(a==b)rot(f),rot(v);        else            rot(v),rot(v);    }};void access(nd* v){    nd* d,* k;for(d=0;v;){        spy(v,0);if(v->cd[1])v->cd[1]->fa=0,v->cd[1]->gfa=v;        v->cd[1]=d;if(d)d->fa=v;mis(v),d=v,v=v->gfa;    }};void mkrot(nd* v){access(v);spy(v,0);v->gfa=0,v->fg^=1;};nd* _dfs(nd* v,int x){    if(v->wg==x)return v;    if(v->cd[0]&&v->cd[0]->mi==x)return _dfs(v->cd[0],x);    return _dfs(v->cd[1],x);};nd* _ldfs(nd* v){    if(v->fg)fgs(v);    return v->cd[1]?_ldfs(v->cd[1]):v;};nd* _rdfs(nd* v){    if(v->fg)fgs(v);    return v->cd[0]?_rdfs(v->cd[0]):v;};nd* _fl(nd* v){return v->cd[0]?_ldfs(v->cd[0]):v->fa;};nd* _fr(nd* v){return v->cd[1]?_rdfs(v->cd[1]):v->fa;};void _cut(nd* v){    if(v->fg)fgs(v);spy(v,0);nd* l=_fl(v),* r=_fr(v);    spy(l,v);spy(r,v);l->fa=r->fa=l->gfa=r->gfa=0;    _delete(v);};void _link(nd* u,nd* v,int x){    nd* d=_new();d->mi=d->wg=x;    access(u);spy(u,0);d->gfa=u;    mkrot(v);v->gfa=d;access(v);spy(d,0);};void _cl(nd* u,nd* v,int x){    int t;mkrot(u);access(v);spy(v,0);    if(v->mi>=x)return;    ts+=(x-v->mi);_cut(_dfs(v,v->mi));_link(u,v,x);};void clit(){    int i,j,d;bool fg;for(cnt=0,i=1;i<=100000;++i){        for(j=i;j<=100000;j+=i)psh(j,i);    }    for(i=1,ts=0;i<=100000;++i){        id[i]=_new();id[i]->mi=id[i]->wg=up;        if(i>1){            j=gp[hd[i]].nx;ts+=gp[j].v;            _link(id[i],id[gp[j].v],gp[j].v);            for(j=gp[j].nx;j;j=gp[j].nx)                _cl(id[i],id[gp[j].v],gp[j].v);        }        rs[i]=ts;    }};bool cl(){    int n;if(scanf("%d",&n)==-1)return 0;    printf("%d\n",rs[n]);    return 1;};int main(){#ifndef ONLINE_JUDGE    freopen("in.txt","r",stdin);    freopen("out.txt","w",stdout);#endif    for(clit();cl(););    return 0;};
0 0
原创粉丝点击