hdu 5398 GCD Tree(LCT动态维护最大生成树)
2017-10-22 10:45
459 查看
题目链接:hdu 5398 GCD Tree
题意:
给你一个n,让你输出一个最大生成树的价值。
有n个点,任意两点有条边,边权为gcd(u,v)。
题解:
由于题意要让你输出所有的1e5内所有的n,所以只能动态维护最大生成树。(LCT可以做到)
显然可能有用的边只能是x向x的因子连的边。
LCT如何来维护最大生成树?一个最简单的办法就是将边变成点,然后用点来记录权值。
然后每次加入一条边(u,v)的时候,LCT查询当前树中的(u,v)链上的最小值val,如果val比加入的边的权值小,
那么就把这条边删掉,然后加入(u,v)。
然后对于这题,可以先将全部的点连向1,然后再来加边,每加入一个点,记录一下答案就行了。
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 #define mst(a,b) memset(a,b,sizeof(a)) 4 using namespace std; 5 typedef pair<int,int>P; 6 namespace LCT 7 { 8 const int N=2e5+7; 9 int f ,son [2],tmp ,lazy ;bool rev ; 10 P sum ,val ,eg ; 11 bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;} 12 void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]);rev[x]^=1;} 13 void add(int x,P c){if(!x)return;val[x]=sum[x]=c;} 14 void pb(int x){if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;} 15 void up(int x){ 16 sum[x]=val[x]; 17 if(son[x][0]) 18 { 19 if(sum[son[x][0]].first<sum[x].first)sum[x]=sum[son[x][0]]; 20 } 21 if(son[x][1]) 22 { 23 if(sum[son[x][1]].first<sum[x].first)sum[x]=sum[son[x][1]]; 24 } 25 } 26 void rotate(int x){ 27 int y=f[x],w=son[y][1]==x; 28 son[y][w]=son[x][w^1]; 29 if(son[x][w^1])f[son[x][w^1]]=y; 30 if(f[y]){ 31 int z=f[y]; 32 if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x; 33 } 34 f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y); 35 } 36 void splay(int x){ 37 int s=1,i=x,y;tmp[1]=i; 38 while(!isroot(i))tmp[++s]=i=f[i]; 39 while(s)pb(tmp[s--]); 40 while(!isroot(x)){ 41 y=f[x]; 42 if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);} 43 rotate(x); 44 } 45 up(x); 46 } 47 void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);} 48 int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;} 49 void makeroot(int x){access(x);splay(x);rev1(x);} 50 void link(int x,int y){makeroot(x);f[x]=y;access(x);} 51 void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;up(x);} 52 void cut(int x,int y){makeroot(x);cutf(y);} 53 P ask(int x,int y){makeroot(x);access(y);splay(y);return sum[y];} 54 } 55 using namespace LCT; 56 vector<int>g ; 57 long long ans ; 58 59 void init() 60 { 61 F(i,2,100000) 62 for(int j=i+i;j<=100000;j+=i) 63 g[j].push_back(i); 64 F(i,1,100000)sum[i]=val[i]=P(N,N); 65 F(i,2,100000) 66 { 67 ans[i]=ans[i-1]; 68 int nd=100000+i; 69 link(nd,1);add(nd,P(1,nd));link(i,nd); 70 eg[nd]=P(1,i),ans[i]++; 71 for(auto &it:g[i]) 72 { 73 P now=ask(i,it); 74 if(it<=now.first)continue; 75 cut(eg[now.second].first,now.second); 76 cut(now.second,eg[now.second].second); 77 ans[i]+=it-now.first; 78 link(now.second,i),add(now.second,P(it,now.second)); 79 link(it,now.second),eg[now.second]=P(i,it); 80 } 81 } 82 } 83 84 int main() 85 { 86 init(); 87 for(int n;~scanf("%d",&n);printf("%lld\n",ans )); 88 return 0; 89 }View Code
相关文章推荐
- [LCT 动态最大生成树] HDU 5398 GCD Tree
- hdu 5398 GCD Tree 2015多校联合训练赛#9 LCT,动态生成树
- 【LCT维护最大生成树】[HDU5389]GCD Tree
- HDU 5398 GCD TREE LCT维护贪心
- hdu 5398:GCD Tree lct
- HDU 5333 Undirected Graph 离线 LCT维护最大生成树+树状数组
- LCT(GCD Tree,HDU 5398)
- HDU 4718 The LCIS on the Tree (动态树LCT)
- hdu 5398 GCD Tree
- HDU 5398 GCD Tree
- hdu5398(lct维护最大生成树)
- hdu5398(lct维护最大生成树)
- Hdu 4718 The LCIS on the Tree 动态树 LCT
- 【动态树】 HDOJ 5398 GCD Tree
- HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)
- (hdu step 6.1.8)Pseudoforest(求有一个环的最大生成树)
- 【HDU】4984 Goffi and Graph 最大生成树
- (hdu 2.1.4)又见GCD(求最大公约数GCD的变化题)
- hdu 1003 Max Sum(动态规划求一维最大子段和)
- BNUOJ39566 Do use segment tree (树链剖分+维护区间最大连续和)