HDU 5398 GCD TREE LCT维护贪心

来源:互联网 发布:电脑mac地址查询方法 编辑:程序博客网 时间:2024/04/26 13:57

HDU 5398 GCD TREE LCT维护贪心

题目链接:传送门

题意:找出一颗1~n的最大生成树,边的权值为连接节点的GCD。

思路:贪心的考虑每条边的权值一定为较小的点的值,将1~n从大到小加入到生成树中,向其因子连边,用LCT维护一下最大生成树就好了。

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <vector>using namespace std;//加边维护最大生成树int now_ans;const int INF=10000010;namespace LCT{    const int INF=1e9;    #define NIL mem    const int max_n=300100;    const int mpool=300100;    struct Node {        int val;        int sum;        int pos,mpos;        bool root,rev;        int l,r;        Node *lch,*rch,*fa;        Node(){            mpos=pos=0;            sum=val=0;        }        Node(int _val,int _pos,Node *_lch,Node* _rch,Node *_fa)        :val(_val),pos(_pos),lch(_lch),rch(_rch),fa(_fa){            mpos=pos;            sum=val;            root=true;            rev=false;        }    }mem[mpool],*pool[mpool];    struct link_cut_tree{        Node *node[3000000];        int tp;        Node *stk[max_n];        int n,tot;        int max1(int a,int b){            if(node[a]->val<node[b]->val){                return a;            }            else {                return b;            }        }        void init(){            NIL->val=INF;            NIL->sum=0;;            node[0]=NIL;            NIL->lch=NIL->rch=NIL->fa=NIL;            NIL->pos=NIL->mpos=0;            tot=0;            for(int i=1;i<max_n;i++){                pool[tot++]=mem+i;            }        }        void build(int _n){            n=_n;            tp=n+1;            for(int i=1;i<=n;i++){                node[i]=new(pool[--tot])Node(0,0,NIL,NIL,NIL);            }        }        void apy(int num,int val,int l,int r){            node[num]=new(pool[--tot])Node(val,num,NIL,NIL,NIL);            node[num]->l=l,node[num]->r=r;        }        void reverse(Node *t){            if(t==NIL)return;            t->rev^=1;            swap(t->rch,t->lch);        }        void pushdown(Node *t){            if(t==NIL)return;            if(t->rev){                t->rev=false;                reverse(t->lch);                reverse(t->rch);            }        }        void update(Node *t){            if(t==NIL)return;            t->mpos=max1(t->pos,max1(t->lch->mpos,t->rch->mpos));            t->sum=t->lch->sum+t->rch->sum+t->val;        }        void zig(Node *t){            Node *f=t->fa,*c=t->rch;            if(f->root)t->root=true,f->root=false;            else (f->fa->lch==f?f->fa->lch:f->fa->rch)=t;            t->fa=f->fa,t->rch=f,f->lch=c,c->fa=f,f->fa=t;            update(f);        }        void zag(Node *t){            Node *f=t->fa,*c=t->lch;            if(f->root)t->root=true,f->root=false;            else (f->fa->lch==f?f->fa->lch:f->fa->rch)=t;            t->fa=f->fa,t->lch=f,f->rch=c,c->fa=f,f->fa=t;            update(f);        }        void splay(Node *t){            Node *p=t;            int top=0;            stk[top]=t;            while(!p->root){                stk[++top]=p->fa;                p=p->fa;            }            while(top>=0){                pushdown(stk[top--]);            }            while(!t->root){                if(t->fa->root){                    if(t->fa->lch==t)zig(t);                    else zag(t);                }                else {                    if(t->fa->fa->lch==t->fa){                        if(t->fa->lch==t)zig(t->fa),zig(t);                        else zag(t),zig(t);                    }                    else {                        if(t->fa->lch==t)zig(t),zag(t);                        else zag(t->fa),zag(t);                    }                }            }            update(t);        }        void evert(Node *t){            t=expose(t);            reverse(t);        }        Node * expose(Node *t){            Node *p=t,*q=NIL;            while(p!=NIL){                splay(p);                p->rch->root=true;                p->rch=q;                q->root=false;                q=p;                update(p);                p=p->fa;            }            return q;        }        void cut(int a,int b){            evert(node[b]);            expose(node[a]);            splay(node[a]);            node[a]->lch->fa=NIL;            node[a]->lch->root=true;            node[a]->lch=NIL;            return;        }        void erase(int a){            int l=node[a]->l,r=node[a]->r;            cut(a,l);            cut(a,r);            pool[tot++]=node[a];            return;        }        Node * getroot(Node *t){            t=expose(t);            while(1){                if(t->lch!=NIL)t=t->lch;                else return t;            }        }        void link(int a,int b){            if(getroot(node[a])==getroot(node[b])){                cut_it(a,b);            }            evert(node[b]);            splay(node[b]);            node[b]->fa=node[a];            expose(node[b]);        }        void Link(int a,int b){            apy(++tp,b,a,b);            link(tp,a);            link(b,tp);        }        void cut_it(int a,int b){            expose(node[a]);            Node *p=node[b],*q=NIL;            int tp;            while(p!=NIL){                splay(p);                if(p->fa==NIL){                    tp=max1(p->pos,max1(p->rch->mpos,q->mpos));                }                p->rch->root=true;                p->rch=q;                p->rch->root=false;                update(p);                q=p;                p=p->fa;            }            now_ans-=node[tp]->val;            erase(tp);        }        void dfs(Node *t){            if(t==NIL)return ;            pushdown(t);            dfs(t->lch);            printf("%d %d\n",t->pos,t->val);            dfs(t->rch);        }    };}LCT::link_cut_tree T;const int  N=100100;vector<int> fac[N];void prepare(){    for(int i=1;i<N;i++){        for(int j=i+i;j<N;j+=i){            fac[j].push_back(i);        }    }}int ans[N];int main(){    prepare();    T.init();    T.build(N-1);    now_ans=0;    for(int i=1;i<N;i++){        for(int j=0;j<fac[i].size();j++){            T.Link(i,fac[i][j]);            now_ans+=fac[i][j];        }        ans[i]=now_ans;    }//    return 0;    int n;    while(scanf("%d",&n)!=EOF){        printf("%d\n",ans[n]);    }    return 0;}
0 0