您的位置:首页 > 运维架构

HDU 5398 GCD TREE LCT维护贪心

2015-08-21 13:10 393 查看

HDU 5398 GCD TREE LCT维护贪心

题目链接:传送门

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

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

[code]#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
;
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
;
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
);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: