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. Leetcode 546. Remove Boxes

    题目链接: https://leetcode.com/problems/remove-boxes/description/ 问题描述 若干个有序排列的box和它们的颜色,每次可以移除若干个连续的颜色相 ...

  2. css3-盒模型新增属性

    box-shadow:跟text-shadow类似,可多层叠加 box-shadow:[inset] x y blur [spread] color inset:投影方式,inset内投影,不加参数外 ...

  3. eclipse集成tomcat日志文件输出配置

    eclipse集成tomcat日志文件输入配置 2015-07-21 00:13 1072人阅读 评论(0) 收藏 举报  分类: tomcat(1)  eclipse Where can I vie ...

  4. js拷贝实例;

    ,]]; // var arr2 =arr1.slice(0); // arr1[0] ="z"; // arr1[2][0] = "v"; // consol ...

  5. ESXi安装时遇到不识别的硬件的处理

    1. 部门新购置了一台inspur 四路 NF8480M4的服务器. 上架之后发现ESXi的标准安装盘无法安装. 找不到磁盘安装介质. 2. 处理办法, 找浪潮专家服务,报上序列号,要上相关的一些软件 ...

  6. PHP + JS 实现大文件分割上传

    服务器上传文件会有一定的限制.避免内存消耗过大影响性能,在 php.ini 配置文件中,有几个影响参数: upload_max_filesize = 2M //PHP最大能接受的文件大小 post_m ...

  7. 几种实现one-hot编码的方式

    方法1 之前写使用sklearn进行数据挖掘-房价预测(4)-数据预处理一文中处理标签类特征时候已经提到过,使用sklearn中提供的LabelEncoder和OneHotEncoder方法 a = ...

  8. PostgreSQL之性能优化(转)

    转载自:https://blog.csdn.net/huangwenyi1010/article/details/72853785 解决问题 前言 PostgreSQL的配置参数作为性能调优的一部分, ...

  9. spring cloud实战与思考(五) JWT之携带敏感信息

    需求: 需要将一些敏感信息保存在JWT中,以便提高业务处理效率. 众所周知JWT协议RFC7519使用Base64Url对Header和Payload的Json字符串进行编解码.A JWT is re ...

  10. Python——socketsever模块

    1.作用:同时与多个客户端通信 import socketserver class MyServer(skcketserver.BaseRequestHandler): def handle(self ...