1. 程式人生 > >CodeForces - 1101D:GCD Counting (樹分治)

CodeForces - 1101D:GCD Counting (樹分治)

You are given a tree consisting of n vertices. A number is written on each vertex; the number on vertex i is equal to ai

.

Let's denote the function g(x,y)

as the greatest common divisor of the numbers written on the vertices belonging to the simple path from vertex x to vertex

y">y (including these two vertices). Also let's denote dist(x,y) as the number of vertices on the simple path between vertices x and y, including the endpoints. dist(x,x)=1 for every vertex x

.

Your task is calculate the maximum value of dist(x,y)

">among such pairs of vertices that g(x,y)>1

.

Input

The first line contains one integer n

— the number of vertices (1n2105)

.

The second line contains

n">n

integers a1, a2, ..., an (1ai2105)

— the numbers written on vertices.

Then n1

lines follow, each containing two integers x and y (1x,yn,xy) denoting an edge connecting vertex x with vertex y

. It is guaranteed that these edges form a tree.

Output

If there is no pair of vertices x,y

such that g(x,y)>1, print 0. Otherwise print the maximum value of dist(x,y)

among such pairs.

Examples Input
3
2 3 4
1 2
2 3
Output
1
Input
3
2 3 4
1 3
2 3
Output
2
Input
3
1 1 1
1 2
2 3
Output
0

題意:讓你求最長的路徑長度,滿足路上gcd不為1;

思路:分治的做法比較暴力,但是時限比較長,有板子就直接上了。 由於gcd具有收斂性,路徑上的gcd不會太多,而且越遠回越接近1,我們記錄每一個gcd的最深的位置即可。  (我用的以前的板子,所以用了map,此題的資料量可以不用map

還有一個思路,我們列舉素因子,然後把含有這個素因子的點標記出來,求他們的最遠距離,更新答案。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=200010;
const int inf=0x7FFFFFFF;
int Laxt[maxn],Next[maxn<<1],To[maxn<<1],cnt,N,sn;
int a[maxn],sz[maxn],son[maxn],vis[maxn],root,res;
int dep[maxn];
ll ans[maxn];
map<int,int>mp,tp;
map<int,int>::iterator it1,it2;
inline void read(int &x) {
    x=0; char c=getchar();
    while(c>'9'||c<'0') c=getchar();
    while(c<='9'&&c>='0') x=(x<<3)+(x<<1)+c-'0',c=getchar();
}
void add(int u,int v){
    Next[++cnt]=Laxt[u];
    Laxt[u]=cnt; To[cnt]=v;
}
void getroot(int u,int fa) //找重心
{
    sz[u]=1; son[u]=0;
    for(int i=Laxt[u];i;i=Next[i]){
        if(To[i]!=fa&&!vis[To[i]]){
            getroot(To[i],u);
            sz[u]+=sz[To[i]];
            son[u]=max(son[u],sz[To[i]]);
        }
    }
    son[u]=max(son[u],sn-son[u]);
    if(root==0||son[root]>son[u]) root=u;
}
void getans(int u,int fa,int num) //對於當前鏈產生的新GCD
{
    dep[u]=dep[fa]+1; tp[num]=max(tp[num],dep[u]);
    for(int i=Laxt[u];i;i=Next[i]){
        if(!vis[To[i]]&&To[i]!=fa){
            getans(To[i],u,__gcd(num,a[To[i]]));
        }
    }
}
void solve(int u) //解決以u為根的子問題
{
    mp.clear(); mp[a[u]]=1; ans[a[u]]++; dep[u]=1;
    for(int i=Laxt[u];i;i=Next[i])
      if(!vis[To[i]]) {
         tp.clear(); getans(To[i],u,__gcd(a[u],a[To[i]]));
         for(it1=mp.begin();it1!=mp.end();it1++)
           for(it2=tp.begin();it2!=tp.end();it2++){
              int g=__gcd((*it1).first,(*it2).first);
              if(g>1) res=max(res,(*it1).second+(*it2).second-1);
        }
        for(it2=tp.begin();it2!=tp.end();it2++)
          mp[(*it2).first]=max((*it2).second,mp[(*it2).first]);
    }
}
void dfs(int u)  //分治
{
    vis[u]=1;  solve(u);
    for(int i=Laxt[u];i;i=Next[i]){
        if(vis[To[i]]) continue;
        root=0; sn=sz[To[i]];
        getroot(To[i],0); dfs(root);
    }
}
int main()
{
    read(N); int u,v,Max=0;
    for(int i=1;i<=N;i++) read(a[i]),Max=max(Max,a[i]);
    for(int i=1;i<N;i++) {
        read(u);read(v);
        add(u,v);  add(v,u);
    }
    if(Max>1) res=1;
    root=0; sn=N; getroot(1,0); dfs(root);
    printf("%d\n",res);
    return 0;
}

 

相關推薦

CodeForces - 1101DGCD Counting 分治

You are given a tree consisting of n vertices. A number is written on each vertex; the number on vertex i is equal to ai . Let's denote the function g(x,

CodeForces - 1073E Segment Sum 數位DP

You are given two integers l l and r r (l≤r l≤r ). Your task is to calculate the sum of numbers from l l to r r (including l&nb

bzoj2599[IOI2011]Race 分治

Problem 求權值和等於 KKK 的路徑中,邊數的最小值。 Solution 點分治… 用 tmp[i]tmp[i]tmp[i] 表示到重心距離為 iii 的最短邊數 那麼 ans=min(ans

HDU - 5324Boring Class CDQ分治&狀陣列&最小字典序

題意:給定N個組合,每個組合有a和b,現在求最長序列,滿足a不升,b不降。 思路:三位偏序,CDQ分治。   但是沒想到怎麼輸出最小字典序,我好菜啊。  最小字典序: 我們倒序CDQ分治,ans[i]表示倒序的以i為結尾的最長序列,如果當前的ans[i]==目前最大,而且滿足序列要求,

CodeForces - 1093GMultidimensional Queries 線段求K維最遠點距離

題意:給定N個K維的點,Q次操作,或者修改點的座標;或者問[L,R]這些點中最遠的點。 思路:因為最後一定可以表示維+/-(x1-x2)+/-(y1-y2)+/-(z1-z2)..... 所以我們可以儲存到線段樹裡,每次求區間最大值和最小值即可。 注意到我們可以先確定一個點的正負號,所以時間和空間節省了

CodeForces - 778C Peterson Polyglot 啟發式合併trie

Peterson loves to learn new languages, but his favorite hobby is making new ones. Language is a set of words, and word is a sequence of lowercase Latin let

CodeForces - 778C Peterson Polyglot 啟發式合並trie

call sin rst malle case containe names esp processes Peterson loves to learn new languages, but his favorite hobby is making new ones. La

Gym - 101002KYATP 分治+二分+斜率優化

給定 clu 這一 一個 mes 斜率優化 還要 printf clas 題意:給定帶點權邊權的樹,定義路徑的花費=路徑邊權和e+起點點權w[s]*終點點權w[t]。N<2e5,e,w<1e6; 思路:首先,需要樹分治。 然後得到方程dp[i]=min{ di

洛谷P3374 【模板】狀數組 1CDQ分治

size 結果 pri amp fine open sum turn 二維 題目描述 如題,已知一個數列,你需要進行下面兩種操作: 1.將某一個數加上x 2.求出某區間每一個數的和 輸入輸出格式 輸入格式: 第一行包含兩個整數N、M,分別表示該數列數字的個

Codeforces-707DPersistent Bookcase 離線處理特殊的可持久化問題&&Bitset

cif books nsis LG AR num eight which bit Recently in school Alina has learned what are the persistent data structures: they are data stru

CodeForces - 651DImage Preview 雙指針&

posit pri uri int turn seconds review 如果 contain Vasya‘s telephone contains n photos. Photo number 1 is currently opened on the phone. It

CodeForces - 662AGambling Nim 求有多少個子集其異或為S(占位)

side des color exactly form rds then swe sequence As you know, the game of "Nim" is played with n piles of stones, where the i-th pile in

資料結構實驗之二叉葉子問題SDUT 3346

#include <bits/stdc++.h> using namespace std; struct node { char data; struct node *lc, *rc; }; char a[100]; int num = 0; struct node

【BZOJ4025】二分圖可撤銷並查集+線段分治

題目: BZOJ4025 分析: 定理:一個圖是二分圖的充要條件是不存在奇環。 先考慮一個弱化的問題:保證所有邊出現的時間段不會交叉,只會包含或相離。 還是不會?再考慮一個更弱化的問題:邊只會出現不會消失。 當加邊的時候,若\((u,v)\)不連通:一定不會構成奇環,將它加入。 若\(

codeforces 1046 a A. AI robots cdq分治

A. AI robots time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output In the

Codeforces-1059D Nature Reserve二分

D. Nature Reserve time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard output There i

CodeForces - 1093DBeautiful Graph二分圖判定+方案數

題意:給定無向圖,讓你給點加權(1,2,3),使得每條邊是兩端點點權和維奇數。 思路:一個連通塊是個二分圖,判定二分圖可以dfs,並查集,2-sat染色。 這裡用的並查集(還可以帶權並查集優化一下,或者乾脆用dfs)。 計數的時候每個連通塊單獨考慮,我們從連通塊的第一個點開始dfs,如果是該填奇數點,那麼

2018.12.08【FJOI2014】【BZOJ4016】【洛谷P2993】最短路徑問題最短路分治

BZOJ傳送門 洛谷傳送門 解析: 辛辛苦苦調了半天發現是最短路樹建錯了。。。 思路: 首先跑一個最短路,然後將每個點的所有出邊按照出點編號排序,DFS建出最短路樹。 這樣建樹才能夠保證字典序是最小的。(naive的我按照前驅結點建樹WA哭了) 那麼看一

luogu P2664 上游戲分治

點分治真是一個好東西。可惜我不會 這種要求所有路經的題很可能是點分治。 然後我就不會了。。 既然要用點分治,就想,點分治有哪些優點?它可以\(O(nlogn)\)遍歷分治樹的所有子樹。 那麼現在的問題就是,如可快速(\(O(n)\)或O\((nlogn)\))求以一個點為根的時候,子樹之間的貢獻(當然還有根節

Codeforces 938G Shortest Path Queries 線段分治+並查集+線性基

題意 給出一個連通帶權無向圖,邊有邊權,要求資瓷q個操作: 1 x y d在原圖中加入一條x到y權值為b的邊 2 x y把圖中x到y的邊刪掉 3 x y表示詢問x到y的異或最短路 保證任意操作後原圖連通無重邊自環且操作均合法 n,m,q<=20