hdu 5398:GCD Tree lct

来源:互联网 发布:unity3d c 脚本编程 编辑:程序博客网 时间:2024/04/19 20:02

       注意到如果(x,y)连边,且d=gcd(x,y)使得d<x且d<y,那么考虑(d,x),(d,y),去掉边(x,y)后d必然和一个不在一起,那么连上这条边即可。也就是最后的任意边(x,y)都是x|y或y|x的

      然后从小到大枚举然后lct维护最大生成树即可。(结果暴力可以怒草lct,QAQ)

AC代码如下:

#include<iostream>#include<cstdio>#include<cstring>#define inf 1000000000#define N 200005#define M 1100005#define isrt(x) (c[fa[x]][0]!=x && c[fa[x]][1]!=x)#define up(x,y) ((a[y]<a[x])?x=(y):0)using namespace std;int n,tp,tot,fa[N],c[N][2],q[N],a[N],pos[N],fst[N],pnt[M],nxt[M],ans[N];bool rev[N];void add(int x,int y){    pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;}void maintain(int x){    pos[x]=x; up(pos[x],pos[c[x][0]]); up(pos[x],pos[c[x][1]]);}void rotate(int x){    int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1;    if (!isrt(y))        if (c[z][0]==y) c[z][0]=x; else c[z][1]=x;    fa[x]=z; fa[y]=x; fa[c[x][r]]=y;    c[y][l]=c[x][r]; c[x][r]=y;    maintain(y);}void pushdn(int x){    if (rev[x]){        swap(c[x][0],c[x][1]);        rev[c[x][0]]^=1; rev[c[x][1]]^=1; rev[x]=0;    }}void splay(int x){    int i,y,z;    for (i=x,tp=0; !isrt(i); i=fa[i]) q[++tp]=i; q[++tp]=i;    while (tp) pushdn(q[tp--]);    for (; !isrt(x); rotate(x)){        y=fa[x]; z=fa[y];        if (!isrt(y)) rotate((c[z][0]==y ^ c[y][0]==x)?x:y);    }maintain(x);}void acss(int x){    int y=0;    for (; x; y=x,x=fa[x]){        splay(x); c[x][1]=y; maintain(x);    }}void makert(int x){ acss(x); splay(x); rev[x]^=1; }void link(int x,int y){ makert(x); fa[x]=y; }int main(){    int i,j,k,x,y;    for (i=1; i<=50000; i++)        for (j=i<<1; j<=100000; j+=i) add(j,i);    a[0]=a[n=2]=inf;    for (i=2; i<=100000; i++){        a[++n]=pnt[fst[i]]; a[++n]=inf;        ans[i]=ans[i-1]+a[n-1];        link(n,n-1); link(n-1,a[n-1]<<1);        for (j=nxt[fst[i]]; j; j=nxt[j]){            k=pnt[j]; y=k<<1;            makert(n); acss(y); splay(y);            if (a[x=pos[y]]<k){                ans[i]+=k-a[x];                splay(x);                fa[c[x][0]]=fa[c[x][1]]=0;                c[x][0]=c[x][1]=0; pos[x]=x;                a[x]=k; link(x,y); link(n,x);            }        }    }    while (~scanf("%d",&i)) printf("%d\n",ans[i]);    return 0;}


by lych

2016.11.13

0 0
原创粉丝点击