【LCT维护最大生成树】[HDU5389]GCD Tree
题目
分析:由于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 0x7fffffff
int 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]);
}
}