hdu5398 GCD Tree(lct)

转载请注明出处: 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

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

  1 /**
  2  * code generated by JHelper
  3  * More info: https://github.com/AlexeyDmitriev/JHelper
  4  * @author xyiyy @https://github.com/xyiyy
  5  */
  6
  7 #include <iostream>
  8 #include <fstream>
  9
 10 //#####################
 11 //Author:fraud
 12 //Blog: http://www.cnblogs.com/fraud/
 13 //#####################
 14 //#pragma comment(linker, "/STACK:102400000,102400000")
 15 #include <iostream>
 16 #include <sstream>
 17 #include <ios>
 18 #include <iomanip>
 19 #include <functional>
 20 #include <algorithm>
 21 #include <vector>
 22 #include <string>
 23 #include <list>
 24 #include <queue>
 25 #include <deque>
 26 #include <stack>
 27 #include <set>
 28 #include <map>
 29 #include <cstdio>
 30 #include <cstdlib>
 31 #include <cmath>
 32 #include <cstring>
 33 #include <climits>
 34 #include <cctype>
 35
 36 using namespace std;
 37 #define XINF INT_MAX
 38 #define INF 0x3FFFFFFF
 39 #define mp(X, Y) make_pair(X,Y)
 40 #define pb(X) push_back(X)
 41 #define rep(X, N) for(int X=0;X<N;X++)
 42 #define rep2(X, L, R) for(int X=L;X<=R;X++)
 43 #define dep(X, R, L) for(int X=R;X>=L;X--)
 44 #define clr(A, X) memset(A,X,sizeof(A))
 45 #define IT iterator
 46 #define ALL(X) (X).begin(),(X).end()
 47 #define PQ std::priority_queue
 48 typedef long long ll;
 49 typedef unsigned long long ull;
 50 typedef pair<int, int> PII;
 51 typedef vector<PII> VII;
 52 typedef vector<int> VI;
 53
 54 const int MAXN = 100010;
 55 int pre[MAXN<<1], ch[MAXN<<1][2], rev[MAXN<<1];
 56 int key[MAXN<<1];
 57 int lx[MAXN<<1],rx[MAXN<<1];
 58 int mx[MAXN<<1];
 59
 60 void push_down(int r) {
 61     if(!r)return;
 62     if (rev[r]) {
 63         rev[ch[r][0]] ^= 1;
 64         rev[ch[r][1]] ^= 1;
 65         swap(ch[r][0], ch[r][1]);
 66         rev[r] ^= 1;
 67     }
 68 }
 69
 70 void push_up(int x) {
 71     int l = ch[x][0],r = ch[x][1];
 72     mx[x] = x;
 73     if(key[mx[l]]<key[mx[x]])mx[x] = mx[l];
 74     if(key[mx[r]]<key[mx[x]])mx[x] = mx[r];
 75 }
 76
 77 void rotate(int x, int d) {
 78     const int y = pre[x];
 79     ch[y][!d] = ch[x][d];
 80     if (ch[x][d])pre[ch[x][d]] = y;
 81     pre[x] = pre[y];
 82     if (ch[pre[y]][0] == y)ch[pre[x]][0] = x;
 83     else if (ch[pre[y]][1] == y)ch[pre[x]][1] = x;
 84     pre[y] = x;
 85     ch[x][d] = y;
 86     push_up(y);
 87 }
 88
 89 bool _splay_parent(int x,int &y){
 90     return (y = pre[x])!=0 && (ch[y][0] == x || ch[y][1] == x);
 91 }
 92
 93 void splay(int x,int goal) {
 94     push_down(x);
 95     for (int y,z;_splay_parent(x,y);) {
 96             //cout<<x<<" "<<y<<endl;
 97         if(_splay_parent(y,z)){
 98             push_down(z);push_down(y);push_down(x);
 99             int d = y == ch[z][0];
100             if(x == ch[y][d])rotate(x,d^1),rotate(x,d);
101             else rotate(y,d),rotate(x,d);
102         }else {
103             push_down(y),push_down(x);
104             rotate(x, x == ch[y][0]);break;
105         }
106     }
107     push_up(x);
108 }
109
110 int access(int u) {
111     int v = 0;
112     for (; u; u = pre[u]) {
113         splay(u,0);
114         ch[u][1] = v;
115         push_up(v = u);
116     }
117     return v;
118 }
119
120 void makeroot(int x) {
121     rev[access(x)] ^= 1;
122     splay(x,0);
123 }
124
125 void link(int x, int y) {
126     makeroot(x);
127     pre[x] = y;
128 }
129
130 void cut(int x, int y) {
131     makeroot(x);
132     access(y);
133     splay(y,0);
134     pre[ch[y][0]] = 0;
135     ch[y][0] = 0;
136     push_up(y);
137 }
138
139 void Init(int n) {
140     for (int i = 0; i < n; i++) {
141         pre[i] = ch[i][0] = ch[i][1] = 0;
142         key[i] = INF;
143         mx[i] = 0;
144     }
145 }
146 void debug(int x){
147
148 }
149 int query(int x, int y) {
150     makeroot(x);
151     access(y);
152     splay(y,0);
153     return mx[y];
154 }
155
156
157 vector<int> vec[MAXN];
158 int ans[MAXN];
159
160 class hdu5398 {
161 public:
162     void solve(std::istream &in, std::ostream &out) {
163         rep2(i, 2,  MAXN-1) {
164             vec[i].pb(1);
165             for (int j = 2; j * j <= i; j++) {
166                 if (i % j == 0) {
167                     vec[i].pb(j);
168                     if (i / j != j)vec[i].pb(i / j);
169                 }
170             }
171             sort(vec[i].begin(),vec[i].end());
172         }
173         Init(MAXN<<1);
174         ans[1] = 0;
175         rep2(i, 2, MAXN-5) {
176             int sz = vec[i].size();
177             int y = vec[i][sz - 1];
178             ans[i] = ans[i - 1];
179             link(i, MAXN + i);
180             rx[MAXN + i] = i;
181             link(y, MAXN + i);
182             lx[MAXN + i] = y;
183             key[MAXN + i] = y;
184             ans[i] += y;
185             dep(j, sz - 2, 0) {
186                 y = vec[i][j];
187                 int x = query(y, i);
188                 cut(x,lx[x]);
189                 cut(x,rx[x]);
190                 link(y, x);
191                 link(i, x);
192                 ans[i] -= key[x];
193                 key[x] = y;
194                 lx[x] = y;
195                 rx[x] = i;
196                 ans[i] += y;
197             }
198         }
199         int n;
200         while(in>>n){
201             out<<ans[n]<<endl;
202         }
203
204     }
205 };
206
207 int main() {
208     std::ios::sync_with_stdio(false);
209     std::cin.tie(0);
210     hdu5398 solver;
211     std::istream &in(std::cin);
212     std::ostream &out(std::cout);
213     solver.solve(in, out);
214     return 0;
215 }
时间: 2024-10-15 16:24:45

hdu5398 GCD Tree(lct)的相关文章

HDU4718 The LCIS on the Tree(LCT)

又是一枚LCT,写一发加深一下对LCT的理解.本题的坑爹之处就在于,它实在是太坑爹了.询问的是树路径上的最长连续上升的子串,考验的是怎么样去维护.一开始的想法是维护三个变量 ls,rs,mxl,分别表示左起最长上升,右末最长上升,以及总的最长上升,那么最长上升一定是可以在下面的条件下求到的, mxl=max(ch[0]->mxl,ch[1]->mxl) 以及 令temp=1 存一下左右区间的左右lval,rval, if val>ch[0]->rval temp+=ch[0]-&g

BZOJ 2631: tree( LCT )

LCT...略麻烦... -------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define rep( i , n ) for( int i = 0 ; i < n ; ++i ) #define

[BZOJ3282]Tree(LCT)

3282: Tree Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 2350  Solved: 1104[Submit][Status][Discuss] Description 给定N个点以及每个点的权值,要你处理接下来的M个操作. 操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和. 保证x到y是联通的. 1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连

BZOJ 3282: Tree [LCT]

3282: Tree Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1677  Solved: 744[Submit][Status][Discuss] Description 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的. 1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接.

spoj 375 query on a tree LCT

这道题是树链剖分的裸题,正在学LCT,用LCT写了,发现LCT代码比树链剖分还短点(但我的LCT跑极限数据用的时间大概是kuangbin大神的树链剖分的1.6倍,所以在spoj上是850ms卡过的). 收获: 1.边转换成点(即若存在边(u,v),则新加一个点z代表边,将z连接u和v,z的点权就是(u,v)的边权,非边点的权设为-oo),然后对边权的统计就变成了对点权的统计(这是LCT中处理边信息的通法之一). 2.若要连接两个点u,v,先让它们分别称为根,然后将其中一个的path-parent

bzoj2631: tree lct

要打mul和add的lct 50000+的mod用unsigned int好了TAT (坑爹没打pc('\n');(静态)调了好久,样例竟然只输出一个,orz,也不提示PE T_T) 1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cstdio> 6 7 using namespace std; 8 9 co

【bzoj3282】Tree LCT

题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的. 1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接. 2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在. 3:后接两个整数(x,y),代表将点X上的权值变成Y. 输入 第1行两个整数,分别为N和M,代表点数和操作数. 第2行到第N+1行,每行一个整

【BZOJ】2631: tree LCT

[题意]给定n个点的树,每个点初始权值为1,m次操作:1.x到y的点加值,2.断一条边并连一条边,保证仍是树,3.x到y的点乘值,4.x到y的点权值和取模.n,m<=10^5. [算法]Link-Cut Tree [题解]区间加和区间乘标记的处理:[BZOJ]1798: [Ahoi2009]Seq 维护序列seq 线段树 splay上维护要注意: 1.上传时加本身. 2.改值的时候不能影响到0点. 3.所有改变点的儿子的地方都要上传,所有改变点的父亲的地方都要下传. 除了rotate,还有acc

动态树Link-Cut Tree(LCT)

简介 一般的树上带修改问题,树剖(轻重链剖分)就可以搞定了,但是万一有连边.断边之类的东西?Good Game. 我们想一想,什么数据结构能处理移动点的问题?平衡树. 那我们就尝试把平衡树挪到树上,这时我们的树剖方式就叫做实链剖分. 定义与性质 先给定义. 实边:包含在一个splay中的边.一条实边恰好包含在一个splay中.一个节点的儿子只有一个连的是实边,其它都是虚边. 虚边:由一个splay的某个节点拉向另一个splay的根节点的边. 实链:一个splay里面从上到下连续的实边(感性理解一