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个祖先关系, 和每个人想给谁送! ...
随机推荐
- 2017-2018-2 1723《程序设计与数据结构》实验四 & 实验五 & 课程总结 总结
作业地址 实验四作业:https://edu.cnblogs.com/campus/besti/CS-IMIS-1723/homework/1943 提交情况如图: 实验五作业:https://edu ...
- HTML编码规则
<!DOCTYPE html><!-- 为每一个HTML页面的第一行添加标准模式 --> <html lang="en-us"> <!-- ...
- nodejs框架对比
最近想实操nodejs,在选择框架的时候,查阅后大致整理为如下表格内容. 此处列举下才开始使用eggjs框架: 1.其基于koa开发: 2.若为企业级项目,用其脚手架egg-inint搭建会快很多,后 ...
- redis的优缺点
优点: 1 读写性能优异 2 支持数据持久化,支持AOF和RDB两种持久化方式 3 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离. 4 数据结构丰富:除了支持string类型的value ...
- sql 表,字段(列),表数据(行)相关命令
随便转载,保留出处:http://www.cnblogs.com/aaron-agu/ 注: 以下所有操作都在登陆数据库后执行 命令use test; test为数据库名 查看表 show tabl ...
- js運算符
運算符算術運算符.邏輯運算符.賦值運算符.比較運算符.條件運算符 字符串的合併,用+,如果是字符串和數字用+連接,則當做字符串合併. 條件運算符:if(條件)?語句1,語句2:
- python之tkinter使用举例-Button
tkinter用于编写GUI界面,python3默认已经包含,直接使用. # GUI:tkinter使用举例 import tkinter # 实例化tkinter对象 top = tkinter.T ...
- BZOJ2822[AHOI2012]树屋阶梯——卡特兰数+高精度
题目描述 暑假期间,小龙报名了一个模拟野外生存作战训练班来锻炼体魄,训练的第一个晚上,教官就给他们出了个难题.由于地上露营湿气重,必须选择在高处的树屋露营.小龙分配的树屋建立在一颗高度为N+1尺(N为 ...
- JPQL设置自增长、只读、文本类型等的注解
JAVA中使用JPQL 一种设置id自动生成,自增长的方法 private long id; @Id @GeneratedValue(generator="_native") @G ...
- 自学Aruba4.2-Aruba AC基础配置(1)
点击返回:自学Aruba之路 自学Aruba4.2-Aruba AC基础配置(1) 管理员登陆(admin/saic_admin): Cli Web 管理帐号 控制器基础设置: 控制器恢复出厂设置 查 ...