CodeForces842C 树上dfs
题意:
有一个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的更多相关文章
- 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 ...
- 【bzoj4813】[Cqoi2017]小Q的棋盘 树上dfs+贪心
题目描述 小Q正在设计一种棋类游戏.在小Q设计的游戏中,棋子可以放在棋盘上的格点中.某些格点之间有连线,棋子只能在有连线的格点之间移动.整个棋盘上共有V个格点,编号为0,1,2…,V-1,它们是连通的 ...
- BZOJ 1232 [Usaco2008Nov]安慰奶牛cheer:最小生成树【树上dfs性质】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1232 题意: 给你一个无向图,n个点,m条边. 每条边有边权len[i][j],每个点有点 ...
- 牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树)
牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树) 链接:https://ac.nowcoder.com/acm/problem/15706 现在需要您来帮忙维护这个名册, ...
- Codeforces 682C Alyona and the Tree (树上DFS+DP)
题目链接:http://codeforces.com/problemset/problem/682/C 题目大意:取树上任意一个点v,若点v的子树中有一个点u使得dist(v,u)>a[u]那么 ...
- Kattis - bitwise Bitwise (RMQ+尺取+树上dfs)
题意:有一个长度为n的序列,让你把它分成k段,段内元素取or,段间取and,求能够得到的最大值. 这个算法是我和xz场上yy出来的,然而时间不够了没写出来,而且时间复杂度是$O(nlogn+nlogA ...
- LightOJ 1224 - DNA Prefix - [字典树上DFS]
题目链接:https://cn.vjudge.net/problem/LightOJ-1224 Given a set of $n$ DNA samples, where each sample is ...
- 【树上DFS】Tree and Polynomials
http://codeforces.com/gym/101372 D push1[i][k]:所有操作1总共要让节点i下推多少系数k push2[i][k]:所有操作2总共要让节点i上推多少系数k s ...
- CodeForces 681D Gifts by the List (树上DFS)
题意:一个家庭聚会,每个人都想送出礼物,送礼规则是, 一个人,先看名单列表,发现第一个祖先 就会送给他礼物,然后就不送了,如果他没找到礼物 他会伤心的离开聚会!告诉你m个祖先关系, 和每个人想给谁送! ...
随机推荐
- s标签s:if和s:set实现一个表格显示为多个表格
1.首先本来这个表格是这样的 2.这时候代码是这样的 <table cellpadding="4"> <tr> <th>指标点</th&g ...
- JavaScript —— 数组
Array方法 1.查找元素 indexOf()用来查找传进来的参数在目标数组中是否存在.如果目标数组包含该参数,就返回该元素在数组中的索引:如果不包含,就返回-1. 如果数组中包含多个相同的元素,i ...
- 关于本科毕业论文《Laguerre小波在数值积分与微分方程数值解中的应用》存在的问题与小结
本科的毕业设计<Laguerre小波在数值积分与微分方程数值解中的应用>是通过Laguerre小波函数来近似表达某个需要求积分或解微分方程的函数,将原函数很难求得函数用小波函数表达出来,这 ...
- Leetcode——50.Pow(x, n)
@author: ZZQ @software: PyCharm @file: leetcode50_myPow.py @time: 2018/11/22 13:58 要求:实现 pow(x, n) , ...
- TimeLine CSS/Javascript 时间线
https://casbootadminserver.herokuapp.com/#/applications/23bd8218/trace
- Oracle重新获取统计信息以及SQLSERVER重建索引
Oracle重新获取统计信息 exec dbms_stats.gather_schema_stats(ownname =>'LCoe739999',options => 'GATHER', ...
- WorkStation 虚拟机迁移到 ESXi的后续处理.
自己遇到了然后按照blog http://blog.sina.com.cn/s/blog_79a8b8e10102w8bm.html 解决 特此记录一下. 将Workstation的vmdk文件导入到 ...
- FICO基础知识(三)
成本中心: 成本中心是企业内的最小职责单位,是每一笔费用的具体接收者.创建成本中心主数据时必须将每个成本中心分配给标准层次结构的某个节点,标准层次结构反映了成本中心与成本中心.成本中心与成本中心组.成 ...
- PKUWC 2019&WC 2019爆零记
PKUWC 2019&WC 2019爆零记 毕竟过了很久了,杂七杂八的东西就不写了,并且除成绩之外的内容不保证其正确性. Day1 T1:看到这道题很舒服啊,枚举top序算合法图的数量,状压D ...
- ref、out与params
ref 把值传递转换为引用传递,侧重于将一个值带到函数中进行改变,再将改变后的值带出去,ref参数在函数外必须为ref参数赋值 ; AddSalary(ref salary); //如果不写ref,s ...