题意:有一颗树,每个点有一个点权,边权都是1,问路径上的所有点的gcd不是1的最长路径是多少?

思路:之前补这道题的时候,用分解质因数 + 树形DP做的,其实用点分治可以更暴力一点。对于这类统计树上路径的问题,点分治是一种通用,高效的解法。对于所有的路径,无非两种情况:经过某个点,不经过某个点,我们对于每个点统计的相当于是经过该点的路径的信息。点分治为以下几步:1:找重心。2:以找到的重心为根,解决经过该点的路径的问题。3:递归的找其它子树的重心,解决问题。找经过该点的路径时,直接搜索求gcd,所有说非常暴力无脑。找到之后暴力合并。复杂度应该是O(n * (log(n) ^ 2));

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200010;
vector<int> G[maxn];
map<int, int> mp, tmp;
map<int, int>::iterator it1, it2;
bool v[maxn];
int sz[maxn], tot, mx, root, a[maxn], ans;
void add(int x, int y) {
G[x].push_back(y);
G[y].push_back(x);
}
void get_root(int x, int fa) {
sz[x] = 1;
int max_part = 0;
for (auto y : G[x]) {
if(y == fa || v[y]) continue;
get_root(y, x);
sz[x] += sz[y];
max_part = max(max_part, sz[y]);
}
max_part = max(max_part, tot - sz[x]);
if(max_part < mx) {
mx = max_part;
root = x;
}
}
void get_ans(int x, int dep, int fa, int z) {
if(z == 1) return;
tmp[z] = max(tmp[z], dep);
for (auto y : G[x]) {
if(v[y] || y == fa) continue;
get_ans(y, dep + 1, x, __gcd(z, a[y]));
}
}
void solve(int x) {
mp.clear();
mp[a[x]] = 1;
for (auto y : G[x]) {
if(v[y]) continue;
tmp.clear();
get_ans(y, 1, x, __gcd(a[x], a[y]));
for (it1 = mp.begin(); it1 != mp.end(); it1++) {
for (it2 = tmp.begin(); it2 != tmp.end(); it2++) {
if(__gcd(it1 -> first, it2 -> first) != 1) {
ans = max(ans, (it1 -> second) + (it2 -> second));
}
}
}
for (it2 = tmp.begin(); it2 != tmp.end(); it2++) {
mp[it2 -> first] = max(mp[it2 -> first], (it2 -> second) + 1);
}
}
}
void div(int x) {
v[x] = 1;
solve(x);
for (auto y : G[x]) {
if(v[y]) continue;
tot = sz[y];
mx = 1e6;
get_root(y, x);
div(root);
}
}
int main() {
int n, x, y;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
if(a[i] > 1) ans = 1;
}
for (int i = 1; i < n; i++) {
scanf("%d%d", &x, &y);
add(x, y);
}
tot = n;
mx = 1e6;
get_root(1, -1);
div(root);
printf("%d\n", ans);
}

  

Codeforces 1101D 点分治的更多相关文章

  1. CodeForces - 1101D:GCD Counting (树分治)

    You are given a tree consisting of n vertices. A number is written on each vertex; the number on ver ...

  2. Codeforces 293E 点分治+cdq

    Codeforces 293E 传送门:https://codeforces.com/contest/293/problem/E 题意: 给你一颗边权一开始为0的树,然后给你n-1次操作,每次给边加上 ...

  3. codeforces 161D 点分治

    传送门:https://codeforces.com/problemset/problem/161/D 题意: 求树上点对距离恰好为k的点对个数 题解: 与poj1741相似 把点分治的模板改一下即可 ...

  4. Codeforces 475D CGCDSSQ(分治)

    题意:给你一个序列a[i],对于每个询问xi,求出有多少个(l,r)对使得gcd(al,al+1...ar)=xi. 表面上是询问,其实只要处理出每个可能的gcd有多少个就好了,当左端点固定的时候,随 ...

  5. Codeforces 888G(分治+trie)

    按位贪心,以当前考虑位是0还是1将数分成两部分,则MST中这两部分之间只会存在一条边,因为一旦有两条或以上的边,考虑两条边在原图中所成的环,显然这两条边有一条是环上的权值最大边,不会出现在MST中.则 ...

  6. Codeforces 888G Xor-MST - 分治 - 贪心 - Trie

    题目传送门 这是一条通往vjudge的高速公路 这是一条通往Codeforces的高速公路 题目大意 给定一个$n$阶完全图,每个点有一个权值$a_{i}$,边$(i, j)$的权值是$(a_{i}\ ...

  7. Codeforces 990G 点分治+暴力

    题意:给出一棵点带权的树,求i\(\in\)[1,200000]所有路径的上点权的gcd==i的个数. 考虑点分治,对于一棵以u为根的子树,如何统计经过u的路径的答案? 显然既然是经过点u的路径,那么 ...

  8. 【题解】Radio stations Codeforces 762E CDQ分治

    虽然说好像这题有其他做法,但是在问题转化之后,使用CDQ分治是显而易见的 并且如果CDQ打的熟练的话,码量也不算大,打的也很快,思维难度也很小 没学过CDQ分治的话,可以去看看我的另一篇博客,是CDQ ...

  9. Radio stations CodeForces - 762E (cdq分治)

    大意: 给定$n$个三元组$(x,r,f)$, 求所有对$(i,j)$, 满足$i<j, |f_i-f_j|\le k, min(r_i,r_j)\ge |x_i-x_j|$ 按$r$降序排, ...

随机推荐

  1. MFC程序执行过程剖析(转)

    一 MFC程序执行过程剖析 1)我们知道在WIN32API程序当中,程序的入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调用 ...

  2. php 从7.0升级到7.2

    下面的方法安装的php是非线程安全的,apache2服务器用不了 1. 添加Ondřej Surý提供的PHP源: sudo apt-get install software-properties-c ...

  3. 190行代码实现mvvm模式

    前言 网上讲 vue 原理,mvvm 模式的实现,数据双向绑定的文章一搜一大堆,不管写的谁好谁坏,都是写的自己的理解,我也发一篇文章记录自己的理解,如果对看官有帮助,那也是我莫大的荣幸,不过看完之后, ...

  4. 16_3.jdk动态代理与aop

    jdk动态代理: public interface Subject { void say(String name,int age); } public class RealSubject implem ...

  5. iPython清屏命令

    !clear for Unix-like systems !CLS for Windows

  6. [转]Win10企业版无法访问共享文件夹

    Win10系统电脑在更新后,当我们访问共享文件夹时可能会出现如下图所示窗口,导致我们无法访问.那么这个问题如何解决呢?具体如下:1. 首先我们按“Windows+R键”打开运行窗口.2. 在该窗口文本 ...

  7. 命令查看当前运行APP的包名和Activity

    先用usb链接手机 启动要查看的程序,命令查看当前运行的包名和Activity更清晰. 使用adb shell dumpsys window | findstr mCurrentFocus  命令查看 ...

  8. Oracle分组函数之ROLLUP

    功能介绍: 首先是进行无字段的聚合,然后在对字段进行从左到右依次组合后聚合 创建表: Create Table score ( classID Int, studentName ), subject ...

  9. spring-boot整合Mybatis案例(注解方式)

    1.运行环境 开发工具:intellij idea JDK版本:1.8 项目管理工具:Maven 4.0.0 2.GITHUB地址 https://github.com/nbfujx/springBo ...

  10. 目前在玩的几款手机挖矿APP

    目前在玩的几款手机挖矿APP 1.网易星球 网易星球app是由网易最新推出的区块链产品,网易星球app用户获得邀请码注册之后就能免费领取数字资产“黑钻”,网易星球app还支持信息安全存储.去中心化价值 ...