【LCT维护最大生成树】[HDU5389]GCD Tree

来源:互联网 发布:iphone序列号查询软件 编辑:程序博客网 时间:2024/04/27 11:58

题目
分析:由于wt(u,v)=gcd(u,v),所以我们枚举gcd,而且只尝试连接gcd和它的倍数,也就是我们尝试连接(i,j),仅当j是i的倍数,至于于为什么,我也不知道。
用LCT维护最大生成树,每次连接一条边时,必定形成一个环,删除这个环中最小边即可。

#include<cstdio>#include<algorithm>#include<vector>using namespace std;#define MAXN 100000#define INF 0x7fffffffint ans[MAXN+10],T,n;vector<int>fac[MAXN];void Read(int &x){    char c;    while(c=getchar(),c!=EOF)        if(c>='0'&&c<='9'){            x=c-'0';            while(c=getchar(),c>='0'&&c<='9')                x=x*10+c-'0';            ungetc(c,stdin);            return;        }    exit(0);}struct node{    int val,lgcd;    bool pre,tag;    node *ch[2],*fa;}splay_tree[MAXN+10];inline void push_down(node *p){    if(p->tag){        p->tag=0;        if(p->ch[0])            p->ch[0]->tag^=1;        if(p->ch[1])            p->ch[1]->tag^=1;        swap(p->ch[0],p->ch[1]);    }}inline int Get_lgcd(node *p){    return p?p->lgcd:INF;}inline void update(node *p){    p->lgcd=min(min(Get_lgcd(p->ch[0]),Get_lgcd(p->ch[1])),p->val);}void push_up(node *p){    if(p->pre)        push_up(p->fa);    push_down(p);}void Rotate(node *x,int d){    node *y=x->fa;    if(y->pre)        y->fa->ch[y==y->fa->ch[1]]=x;    x->fa=y->fa;    if(x->ch[d])        x->ch[d]->fa=y;    y->ch[!d]=x->ch[d];    x->ch[d]=y;    y->fa=x;    swap(x->pre,y->pre);    update(y);}void splay(node *x){    node *y,*z;    push_up(x);    while(x->pre){        y=x->fa;        z=y->fa;        if(!y->pre){            if(x==y->ch[0])                Rotate(x,1);            else                Rotate(x,0);        }        else if(y==z->ch[0])            if(x==y->ch[0]){                Rotate(y,1);                Rotate(x,1);            }            else{                Rotate(x,0);                Rotate(x,1);            }        else            if(x==y->ch[1]){                Rotate(y,0);                Rotate(x,0);            }            else{                Rotate(x,1);                Rotate(x,0);            }    }    update(x);}void access(node *x){    node *y=0,*z=x;    while(x){        splay(x);        if(x->ch[1])            x->ch[1]->pre=0;        x->ch[1]=y;        if(y)            y->pre=1;        y=x;        x=x->fa;    }    splay(z);}inline void link(node *x,node *y){    access(x);    access(y);    y->pre=y->tag=1;    x->ch[1]=y;    y->fa=x;    update(x);}void prepare(){    int i,j,d,nans=0,d2;    node *x,*y,*z;    vector<int>::iterator k;    splay_tree[1].val=splay_tree[1].lgcd=1;    for(i=2;i<=MAXN;i++){        splay_tree[i].val=splay_tree[i].lgcd=i;        link(splay_tree+i,splay_tree+1);        nans++;        for(j=i+i;j<=MAXN;j+=i)            fac[j].push_back(i);        for(k=fac[i].begin();k!=fac[i].end();k++){            d=*k;            x=splay_tree+i;            y=splay_tree+d;            access(x);            x->tag=1;            access(y);            d2=y->lgcd;            if(d2<d){                nans+=d-d2;                z=splay_tree+d2;                access(z);                splay(z);                push_down(z);                if(z->ch[0]){                    z->ch[0]->fa=0;                    z->ch[0]->pre=0;                    z->ch[0]=0;                }                else{                    z->ch[1]->fa=0;                    z->ch[1]->pre=0;                    z->ch[1]=0;                }                update(splay_tree+d2);                link(x,y);            }        }        ans[i]=nans;    }}int main(){    prepare();    while(1){        Read(n);        printf("%d\n",ans[n]);    }}
0 0
原创粉丝点击