http://codeforces.com/problemset/problem/842/C

题意:

有一个n个节点的数,每个点有一个点权,根到这个点的所有点权(包括这个点和根)的gcd值为这个点的答案. 对于每一个点的答案,你可以删除其到根节点的路径上的至多一个点来使答案最大. 求每个点的答案(最大值). PS:根为1号点

n,x:[1,2e5]

很显然,这一题看数据就觉得是一发dfs解决的题目,仔细想想果然如此。

一个一点也不显而易见的思想是分别讨论去掉的点在根结点上和不在根节点上的情况。

如果在根节点上,所有节点的答案一定是根结点的因数,预处理出根节点所有的因数,判断所有节点是否含有这些因数。

dfs一遍,用一个vector存储这些因数在遍历到这个点出现的次数,用一个deep表示这个点当前的深度,这些因数排序之后反向扫一遍出现的次数,如果出现的次数大于等于deep - 1,表示这个是有可能的答案。

如果不在根节点上,简单的一批,直接取根结点的答案是0,向下正常找gcd就是这个点可能的答案。

两个可能的答案比较一下取较大值。

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
const int MAXBUF=;char buf[MAXBUF],*ps=buf,*pe=buf+;
inline bool isdigit(const char& n) {return (n>=''&&n<='');}
inline void rnext(){if(++ps==pe)pe=(ps=buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin);}
template <class T> inline bool in(T &ans){
#ifdef VSCode
ans=;T f=;register char c;
do{c=getchar();if ('-'==c)f=-;}while(!isdigit(c)&&c!=EOF);
if(c==EOF)return false;do{ans=(ans<<)+(ans<<)+c-;
c=getchar();}while(isdigit(c)&&c!=EOF);ans*=f;return true;
#endif
#ifndef VSCode
ans =;T f=;if(ps==pe)return false;do{rnext();if('-'==*ps)f=-;}
while(!isdigit(*ps)&&ps!=pe);if(ps==pe)return false;do{ans=(ans<<)+(ans<<)+*ps-;
rnext();}while(isdigit(*ps)&&ps!=pe);ans*=f;return true;
#endif
}const int MAXOUT=;
char bufout[MAXOUT], outtmp[],*pout = bufout, *pend = bufout+MAXOUT;
inline void write(){fwrite(bufout,sizeof(char),pout-bufout,stdout);pout = bufout;}
inline void out_char(char c){*(pout++)=c;if(pout==pend)write();}
inline void out_str(char *s){while(*s){*(pout++)=*(s++);if(pout==pend)write();}}
template <class T>inline void out_int(T x) {if(!x){out_char('');return;}
if(x<)x=-x,out_char('-');int len=;while(x){outtmp[len++]=x%+;x/=;}outtmp[len]=;
for(int i=,j=len-;i<j;i++,j--) swap(outtmp[i],outtmp[j]);out_str(outtmp);}
template<typename T, typename... T2>
inline int in(T& value, T2&... value2) { in(value); return in(value2...); }
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
#define Vec Point
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,tmp,K;
int w[maxn];
struct Edge{
int to,next;
}edge[maxn * ];
int head[maxn],cnt;
void init(){Mem(head,);cnt = ;};
void add(int u,int v){edge[++cnt].to = v;edge[cnt].next = head[u]; head[u] = cnt;}
VI P[maxn];
int l;
int ans[maxn];
int Ans[maxn];
void dfs(int root,int deep,int last){
for(int i = ; i < l; i ++){
if(P[root][i]) Ans[i]++;
}
for(int i = l - ; i >= ; i --){
if(Ans[i] >= deep - ){
ans[root] = max(P[][i],ans[root]);
break;
}
}
for(int i = head[root]; i ;i = edge[i].next){
int v = edge[i].to;
if(v == last) continue;
dfs(v,deep + ,root);
}
for(int i = ; i < l ; i ++){
if(P[root][i]) Ans[i]--;
}
}
void dfs2(int t,int GCD,int last){
ans[t] = GCD;
for(int i = head[t] ; i ; i = edge[i].next){
int v = edge[i].to;
if(v == last) continue;
dfs2(v,__gcd(GCD,w[v]),t);
}
}
void solve(){
for(int i = ; i <= sqrt(w[]); i ++){
if(!(w[] % i)){
P[].push_back(i);
if(i != w[] / i) P[].push_back(w[] / i);
}
}
for(int i = head[]; i ; i = edge[i].next){
int u = edge[i].to;
dfs2(u,w[u],);
}
sort(P[].begin(),P[].end());
l = P[].size();
For(i,,N){
for(int j = ; j < l; j ++){
int v = P[][j];
if(!(w[i] % v)) P[i].push_back();
else P[i].push_back();
}
}
dfs(,,-);
For(i,,N){
printf("%d ",ans[i]);
}
}
int main()
{
in(N);
init();
For(i,,N) in(w[i]);
For(i,,N - ){
int u,v; in(u,v);
add(u,v); add(v,u);
}
solve();
#ifdef VSCode
write();
system("pause");
#endif
return ;
}

当然也有另外的方法,由于gcd的数量较少,所以可能性也就这么点,

用vector[maxn] 表示在当前节点所有的gcd可能性,GCD表示当前到这个点一个数都没扔的可能性。

在向下递推的之后采用01背包的思想,取这个数就把这个数和上一层dp里面所有的数都gcd一遍扔进去。

不取这个数就直接将上一个数的gcd扔进去。

注意扔完之后要去重,学习到了一个简单的vector去重操作

sort(P.begin(),P.end());

erase(unique(P.begin(),P.end()),P.end());

看起来很帅

还有一个简单的输出vecotor最后一个数字的操作

Pri(P.back());

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
const int MAXBUF=;char buf[MAXBUF],*ps=buf,*pe=buf+;
inline bool isdigit(const char& n) {return (n>=''&&n<='');}
inline void rnext(){if(++ps==pe)pe=(ps=buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin);}
template <class T> inline bool in(T &ans){
#ifdef VSCode
ans=;T f=;register char c;
do{c=getchar();if ('-'==c)f=-;}while(!isdigit(c)&&c!=EOF);
if(c==EOF)return false;do{ans=(ans<<)+(ans<<)+c-;
c=getchar();}while(isdigit(c)&&c!=EOF);ans*=f;return true;
#endif
#ifndef VSCode
ans =;T f=;if(ps==pe)return false;do{rnext();if('-'==*ps)f=-;}
while(!isdigit(*ps)&&ps!=pe);if(ps==pe)return false;do{ans=(ans<<)+(ans<<)+*ps-;
rnext();}while(isdigit(*ps)&&ps!=pe);ans*=f;return true;
#endif
}const int MAXOUT=;
char bufout[MAXOUT], outtmp[],*pout = bufout, *pend = bufout+MAXOUT;
inline void write(){fwrite(bufout,sizeof(char),pout-bufout,stdout);pout = bufout;}
inline void out_char(char c){*(pout++)=c;if(pout==pend)write();}
inline void out_str(char *s){while(*s){*(pout++)=*(s++);if(pout==pend)write();}}
template <class T>inline void out_int(T x) {if(!x){out_char('');return;}
if(x<)x=-x,out_char('-');int len=;while(x){outtmp[len++]=x%+;x/=;}outtmp[len]=;
for(int i=,j=len-;i<j;i++,j--) swap(outtmp[i],outtmp[j]);out_str(outtmp);}
template<typename T, typename... T2>
inline int in(T& value, T2&... value2) { in(value); return in(value2...); }
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
#define Vec Point
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,tmp,K;
int w[maxn];
struct Edge{
int to,next;
}edge[maxn * ];
int head[maxn],cnt;
void init(){Mem(head,);cnt = ;};
void add(int u,int v){edge[++cnt].to = v;edge[cnt].next = head[u]; head[u] = cnt;}
VI dp[maxn];
int GCD[maxn];
void dfs(int t,int last){
if(~last){
GCD[t] = __gcd(GCD[last],w[t]);
dp[t].pb(GCD[last]);
for(int i = ; i < dp[last].size(); i ++){
int v = dp[last][i];
dp[t].pb(__gcd(v,w[t]));
}
sort(dp[t].begin(),dp[t].end());
dp[t].erase(unique(dp[t].begin(),dp[t].end()),dp[t].end());
}else{
GCD[t] = w[t];
dp[t].pb();
dp[t].pb(w[t]);
}
for(int i = head[t]; i ; i = edge[i].next){
int v = edge[i].to;
if(v == last) continue;
dfs(v,t);
}
}
void solve(){
dfs(,-);
For(i,,N){
printf("%d ",dp[i].back());
}
}
int main()
{
in(N);
init();
For(i,,N) in(w[i]);
For(i,,N - ){
int u,v; in(u,v);
add(u,v); add(v,u);
}
solve();
#ifdef VSCode
write();
system("pause");
#endif
return ;
}

CodeForces842C 树上dfs的更多相关文章

  1. Kuro and Walking Route CodeForces - 979C (树上DFS)

    Kuro is living in a country called Uberland, consisting of nn towns, numbered from 11to nn, and n−1n ...

  2. 【bzoj4813】[Cqoi2017]小Q的棋盘 树上dfs+贪心

    题目描述 小Q正在设计一种棋类游戏.在小Q设计的游戏中,棋子可以放在棋盘上的格点中.某些格点之间有连线,棋子只能在有连线的格点之间移动.整个棋盘上共有V个格点,编号为0,1,2…,V-1,它们是连通的 ...

  3. BZOJ 1232 [Usaco2008Nov]安慰奶牛cheer:最小生成树【树上dfs性质】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1232 题意: 给你一个无向图,n个点,m条边. 每条边有边权len[i][j],每个点有点 ...

  4. 牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树)

    牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树) 链接:https://ac.nowcoder.com/acm/problem/15706 现在需要您来帮忙维护这个名册, ...

  5. Codeforces 682C Alyona and the Tree (树上DFS+DP)

    题目链接:http://codeforces.com/problemset/problem/682/C 题目大意:取树上任意一个点v,若点v的子树中有一个点u使得dist(v,u)>a[u]那么 ...

  6. Kattis - bitwise Bitwise (RMQ+尺取+树上dfs)

    题意:有一个长度为n的序列,让你把它分成k段,段内元素取or,段间取and,求能够得到的最大值. 这个算法是我和xz场上yy出来的,然而时间不够了没写出来,而且时间复杂度是$O(nlogn+nlogA ...

  7. LightOJ 1224 - DNA Prefix - [字典树上DFS]

    题目链接:https://cn.vjudge.net/problem/LightOJ-1224 Given a set of $n$ DNA samples, where each sample is ...

  8. 【树上DFS】Tree and Polynomials

    http://codeforces.com/gym/101372 D push1[i][k]:所有操作1总共要让节点i下推多少系数k push2[i][k]:所有操作2总共要让节点i上推多少系数k s ...

  9. CodeForces 681D Gifts by the List (树上DFS)

    题意:一个家庭聚会,每个人都想送出礼物,送礼规则是, 一个人,先看名单列表,发现第一个祖先 就会送给他礼物,然后就不送了,如果他没找到礼物 他会伤心的离开聚会!告诉你m个祖先关系, 和每个人想给谁送! ...

随机推荐

  1. Linux内核及分析 第五周 扒开系统调用的三层皮(下)

    实验内容: 1.执行rm menu -rf命令,强制删除原有的menu 2.使用git命令 git clone https://github.com/mengning/menu.git 克隆新的men ...

  2. 网络:Session原理及存储

    一.Session的工作流程 二.会话保持 会话保持是负载均衡最常见的问题之一,会话保持是指在负载均衡器上实现的一种机制,可以识别客户端与服务器之间交互过程的关连性,在作负载均衡的同时还保证一系列相关 ...

  3. checkbox未选中不提交数据

    如果checkbox为选中的话提交的数据为NULL function checkForm() { alert(($("#checkbox").get(0).checked)); i ...

  4. EnglishGame

    https://github.com/zhangxue520/EnglishGame/blob/master/EnglishGame <程序设计实践I> 题目:       打字训练测试软 ...

  5. 第三个Sprint冲刺第五天(燃尽图)

  6. shell脚本--权限分配

    因为shell脚本内部是很多命令的集合,这些命令也许会涉及到操作某一个文件,而且shell脚本的运行,也是需要当前用户对脚本具有运行的权限,否则,会因为权限不够而失败. 首先最重要的一点:修改权限,只 ...

  7. 反编译微信小程序

    最近看了个微信小程序古诗词全集,想知道他的前后端是怎么实现的,所以就想到了反编译.小程序安装后会有个wxapkg格式的文件存在/data/data/com.tencent.mm/MicroMsg/** ...

  8. Linux文件权限属性后面有个点

    坑啊,新上的机器,监控怎么都不好使,各种报错说:没有权限 什么情况? 仔细查看,发现文件权限属性后面怎么多了个点,类似如下: 这是什么? 原来: 开启了SELinux功能的Linux系统就会有这个点. ...

  9. yield与递归的组合运用

  10. LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)

    Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...