转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud

GCD Tree

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 84    Accepted Submission(s): 38

Problem Description
Teacher Mai has a graph with n vertices numbered from 1 to n. For every edge(u,v), the weight is gcd(u,v). (gcd(u,v) means the greatest common divisor of number u and v).

You need to find a subset of the edges that forms a tree that includes every vertex, where the total weight of all the edges in the tree is maximized. Print the total weight of these edges.

 



Input
There are multiple test cases(about 105).

For each test case, there is only one line contains one number n(1≤n≤105).

 



Output
For each test case, print the answer.
 



Sample Input
1
2
3
4
5
 



Sample Output
0
1
2
4
5

LCT维护最大生成树,从小到大不断加入数的时候,先和它最大的约数连边,这样就已经变成一棵树了,然后从大到小依次查询其他因子,每次查找到这个数的路径上的最小值,然后砍断这条边,把i和这次查询的因子相连,因为砍掉的边的权值一定不会超过新加的边,所以每次都在增大,这样能够保证最优

队友随手过了这题。23333333

我的写法是把边权搞成一个点,其实不这样也行,找出最小的点,然后看一下在路径上和这个点相邻的点。

 /**
* code generated by JHelper
* More info: https://github.com/AlexeyDmitriev/JHelper
* @author xyiyy @https://github.com/xyiyy
*/ #include <iostream>
#include <fstream> //#####################
//Author:fraud
//Blog: http://www.cnblogs.com/fraud/
//#####################
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype> using namespace std;
#define XINF INT_MAX
#define INF 0x3FFFFFFF
#define mp(X, Y) make_pair(X,Y)
#define pb(X) push_back(X)
#define rep(X, N) for(int X=0;X<N;X++)
#define rep2(X, L, R) for(int X=L;X<=R;X++)
#define dep(X, R, L) for(int X=R;X>=L;X--)
#define clr(A, X) memset(A,X,sizeof(A))
#define IT iterator
#define ALL(X) (X).begin(),(X).end()
#define PQ std::priority_queue
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef vector<PII> VII;
typedef vector<int> VI; const int MAXN = ;
int pre[MAXN<<], ch[MAXN<<][], rev[MAXN<<];
int key[MAXN<<];
int lx[MAXN<<],rx[MAXN<<];
int mx[MAXN<<]; void push_down(int r) {
if(!r)return;
if (rev[r]) {
rev[ch[r][]] ^= ;
rev[ch[r][]] ^= ;
swap(ch[r][], ch[r][]);
rev[r] ^= ;
}
} void push_up(int x) {
int l = ch[x][],r = ch[x][];
mx[x] = x;
if(key[mx[l]]<key[mx[x]])mx[x] = mx[l];
if(key[mx[r]]<key[mx[x]])mx[x] = mx[r];
} void rotate(int x, int d) {
const int y = pre[x];
ch[y][!d] = ch[x][d];
if (ch[x][d])pre[ch[x][d]] = y;
pre[x] = pre[y];
if (ch[pre[y]][] == y)ch[pre[x]][] = x;
else if (ch[pre[y]][] == y)ch[pre[x]][] = x;
pre[y] = x;
ch[x][d] = y;
push_up(y);
} bool _splay_parent(int x,int &y){
return (y = pre[x])!= && (ch[y][] == x || ch[y][] == x);
} void splay(int x,int goal) {
push_down(x);
for (int y,z;_splay_parent(x,y);) {
//cout<<x<<" "<<y<<endl;
if(_splay_parent(y,z)){
push_down(z);push_down(y);push_down(x);
int d = y == ch[z][];
if(x == ch[y][d])rotate(x,d^),rotate(x,d);
else rotate(y,d),rotate(x,d);
}else {
push_down(y),push_down(x);
rotate(x, x == ch[y][]);break;
}
}
push_up(x);
} int access(int u) {
int v = ;
for (; u; u = pre[u]) {
splay(u,);
ch[u][] = v;
push_up(v = u);
}
return v;
} void makeroot(int x) {
rev[access(x)] ^= ;
splay(x,);
} void link(int x, int y) {
makeroot(x);
pre[x] = y;
} void cut(int x, int y) {
makeroot(x);
access(y);
splay(y,);
pre[ch[y][]] = ;
ch[y][] = ;
push_up(y);
} void Init(int n) {
for (int i = ; i < n; i++) {
pre[i] = ch[i][] = ch[i][] = ;
key[i] = INF;
mx[i] = ;
}
}
void debug(int x){ }
int query(int x, int y) {
makeroot(x);
access(y);
splay(y,);
return mx[y];
} vector<int> vec[MAXN];
int ans[MAXN]; class hdu5398 {
public:
void solve(std::istream &in, std::ostream &out) {
rep2(i, , MAXN-) {
vec[i].pb();
for (int j = ; j * j <= i; j++) {
if (i % j == ) {
vec[i].pb(j);
if (i / j != j)vec[i].pb(i / j);
}
}
sort(vec[i].begin(),vec[i].end());
}
Init(MAXN<<);
ans[] = ;
rep2(i, , MAXN-) {
int sz = vec[i].size();
int y = vec[i][sz - ];
ans[i] = ans[i - ];
link(i, MAXN + i);
rx[MAXN + i] = i;
link(y, MAXN + i);
lx[MAXN + i] = y;
key[MAXN + i] = y;
ans[i] += y;
dep(j, sz - , ) {
y = vec[i][j];
int x = query(y, i);
cut(x,lx[x]);
cut(x,rx[x]);
link(y, x);
link(i, x);
ans[i] -= key[x];
key[x] = y;
lx[x] = y;
rx[x] = i;
ans[i] += y;
}
}
int n;
while(in>>n){
out<<ans[n]<<endl;
} }
}; int main() {
std::ios::sync_with_stdio(false);
std::cin.tie();
hdu5398 solver;
std::istream &in(std::cin);
std::ostream &out(std::cout);
solver.solve(in, out);
return ;
}

hdu5398 GCD Tree(lct)的更多相关文章

  1. HDU 5002 Tree LCT 区间更新

    Tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.action?c ...

  2. BZOJ 3282: Tree( LCT )

    LCT.. -------------------------------------------------------------------------------- #include<c ...

  3. BZOJ 2631: tree( LCT )

    LCT...略麻烦... -------------------------------------------------------------------------------- #inclu ...

  4. [bzoj3282]Tree (lct)

    昨天看了一天的lct..当然幸好最后看懂了(也许吧..) 论善良学长的重要性T_T,老司机带带我! 这题主要是删边的时候还要判断一下..蒟蒻一开始天真的以为存在的边才能删结果吃了一发wa... 事实是 ...

  5. Link-Cut Tree(LCT)&TopTree讲解

    前言: Link-Cut Tree简称LCT是解决动态树问题的一种数据结构,可以说是我见过功能最强大的一种树上数据结构了.在此与大家分享一下LCT的学习笔记.提示:前置知识点需要树链剖分和splay. ...

  6. 动态树Link-cut tree(LCT)总结

    动态树是个好玩的东西 LCT题集 预备知识 Splay 树链剖分(好像关系并不大) 动态树(Link-cut tree) 先搬dalao博客 什么是LCT? 动态树是一类要求维护森林的连通性的题的总称 ...

  7. 洛谷P3690 [模板] Link Cut Tree [LCT]

    题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...

  8. 浅谈Link-Cut Tree(LCT)

    0XFF 前言&概念 Link-Cut Tree 是一种用来维护动态森林连通性的数据结构,适用于动态树问题.它采用类似树链剖分的轻重边路径剖分,把树边分为实边和虚边,并用 Splay 来维护每 ...

  9. Link-Cut Tree(LCT)

    转载自LCT(Link-Cut Tree)详解(蒟蒻自留地) 如果你还没有接触过LCT,你可以先看一看这里: (看不懂没关系,先留个大概的印像)http://www.cnblogs.com/BLADE ...

随机推荐

  1. PHP开发环境设置

    步骤有三个: Apache 服务器安装.PHP 安装和让 Apache 支持 PHP 1. Apache 服务器的安装与配置 基于Windows操作系统支持的PHP开发的服务器有IIS和Apache, ...

  2. 『局域网安全』利用ARP欺骗劫持Cookie

    0x 00 ARP欺骗说明 欺骗原理相关内容就不多叙述了,百度一大堆 实施ARP欺骗在Windows下,Linux下都相关工具 由于在Linux下可以开启ip_forward功能,个人认为Linux下 ...

  3. 在QLabel上点击获得的效果

    一般说只在button中点击获得事件,作出相应的反应.而往往需要在QLabel上作出点击和触碰的效果. 我用qlabel做出了一个效果,当鼠标碰到label区域,label底下出现一条线,离开后线条消 ...

  4. [Operating System Labs] 我对Linux0.00中 head.s 的理解和注释

    ?21,#  head.s contains the 32-bit startup code.#  head.s 是32位的启动代码 #  Two L3 task multitasking. The ...

  5. NERDTree这个插件的用法简介

    事情是这样子的,想做做李治军老师班的操作系统实验,但是Linux上的gedit太简陋了(这个简陋程度堪比Windows环境下的"记事本"),被杨世祺大神嘲笑了.我心想既然在linu ...

  6. MySQL日期函数

    1.已知出生日期,求年龄 SELECT '1992-04-10' as birthday, curdate(), ( YEAR (curdate()) - YEAR ('1992-04-10')-1 ...

  7. 【自由谈】城域网IPv6过渡技术——4v6场景技术总结(1)

    为什么会存在4v6应用场景?主要是从“云-管-端”的IPv6状态决定的,“云”侧IPv4类业务丰富,IPv6驱动力小,所以“云”在较长一段时间内还是以IPv4类业务为主.“管”侧的IPv6化程度高,设 ...

  8. C++基础学习笔记----第十三课(操作符重载-下)

    本节主要讲使用成员函数重载操作符,包括[],=,(),->四种操作符的重载以及&&和||的问题. 类的成员函数进行操作符重载 基本概念 类的成员函数也可以进行操作符的重载.类的普 ...

  9. Javascript 精髓整理篇之三(数组篇)postby:http://zhutty.cnblogs.com

    今天讲js的数组.数组是js中最基础的数据结构了. 主要讲讲数组实现栈,队列以及其他的基本操作.栈和队列都可以在数组头尾位置处理,所以,都有两种方式. 属性 1.length : 长度,表示数组元素的 ...

  10. android repo库的创建及代码管理