金题大战Vol.0 C、树上的等差数列
金题大战Vol.0 C、树上的等差数列
题目描述
给定一棵包含\(N\)个节点的无根树,节点编号\(1-N\)。其中每个节点都具有一个权值,第\(i\)个节点的权值是\(A_i\)。
小\(Hi\)希望你能找到树上的一条最长路径,满足沿着路径经过的节点的权值序列恰好构成等差数列。
输入格式
第一行包含一个整数\(N\)。
第二行包含\(N\)个整数\(A_1, A_2, ... A_N\)。
以下\(N-1\)行,每行包含两个整数\(U\)和\(V\),代表节点\(U\)和\(V\)之间有一条边相连。
输出格式
最长等差数列路径的长度
样例
样例输入
7
3 2 4 5 6 7 5
1 2
1 3
2 7
3 4
3 5
3 6
样例输出
4
数据范围与提示
对于\(50\%\)的数据,\(1 ≤ N ≤ 1000\)
对于\(100\%\)的数据,\(1 ≤ N ≤ 100000, 0 ≤ Ai ≤ 100000, 1 ≤ U, V ≤ N\)
分析
树形\(DP\)
我们设 \(f[i][j]\) 为以\(i\)作为根节点的子树中公差为\(j\)的路径的最长长度,接下来考虑转移
转移的过程无非是把子树中的状态递归至父亲节点
即 \(f[now][a[now]-a[u]]=max(f[now][a[now]-a[u]],f[u][a[now]-a[u]]+1)\)
其中 \(now\) 为父亲节点,\(u\)为儿子节点
统计答案时,我们只要在所有的\(f[now][val]+f[now][-val]+1\)中取最大值就可以了
其实就是把两条链拼在一起
加上一是为了防止特判一些奇奇怪怪的边界问题,比如说只有一个点的情况
要注意 \(0\) 的时候要特判一下,因为此时\(val\)和\(-val\) 相等,直接更新会出错
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
struct asd{
int from,to,next;
}b[maxn];
int head[maxn],tot=1,n,a[maxn],ans=0;
inline void ad(int aa,int bb){
b[tot].from=aa;
b[tot].to=bb;
b[tot].next=head[aa];
head[aa]=tot++;
}
inline int read(){
register int x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
map<int,int>f[maxn];
void dfs(int now,int fa){
int max0=0;
for(int i=head[now];i!=-1;i=b[i].next){
int u=b[i].to;
if(u==fa) continue;
dfs(u,now);
if(a[u]==a[now]){
if(f[now][0]<=f[u][0]+1){
max0=f[now][0];
f[now][0]=f[u][0]+1;
}
else if(max0<f[u][0]+1) max0=f[u][0]+1;
ans=max(ans,f[now][0]+max0+1);
} else {
f[now][a[now]-a[u]]=max(f[now][a[now]-a[u]],f[u][a[now]-a[u]]+1);
ans=max(ans,f[now][a[now]-a[u]]+f[now][a[u]-a[now]]+1);
}
}
}
int main(){
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
memset(head,-1,sizeof(head));
n=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
for(register int i=1;i<n;i++){
register int aa,bb;
aa=read(),bb=read();
ad(aa,bb);
ad(bb,aa);
}
dfs(1,0);
printf("%d\n",ans);
return 0;
}
金题大战Vol.0 C、树上的等差数列的更多相关文章
- 金题大战Vol.0 A、凉宫春日的叹息
金题大战Vol.0 A.凉宫春日的叹息 题目描述 给定一个数组,将其所有子区间的和从小到大排序,求第 \(k\) 小的是多少. 输入格式 第一行两个数\(n\),$ k\(,表示数组的长度和\)k$: ...
- 金题大战Vol.0 B、序列
金题大战Vol.0 B.序列 题目描述 给定两个长度为 \(n\) 的序列\(a\), \(b\). 你需要选择一个区间\([l,r]\),使得\(a_l+-+a_r>=0\)且\(b_l+-+ ...
- 土题大战Vol.0 A. 笨小猴 思维好题
土题大战Vol.0 A. 笨小猴 思维好题 题目描述 驴蛋蛋有 \(2n + 1\) 张 \(4\) 星武器卡片,每张卡片上都有两个数字,第 \(i\) 张卡片上的两个数字分别是 \(A_i\) 与 ...
- 火题大战Vol.0 B 计数DP
火题大战Vol.0 B 题目描述 \(n\) 个沙茶,被编号 \(1\)~$ n$.排完队之后,每个沙茶希望,自己的相邻的两人只要无一个人的编号和自己的编号相差为 \(1\)(\(+1\) 或\(-1 ...
- 水题大战Vol.3 B. DP搬运工2
水题大战Vol.3 B. DP搬运工2 题目描述 给你\(n,K\),求有多少个\(1\)到\(n\) 的排列,恰好有\(K\)个数\(i\) 满足\(a_{i-1},a_{i+1}\) 都小于\(a ...
- 火题大战Vol.1 A.
火题大战Vol.1 A. 题目描述 给定两个数\(x\),\(y\),比较\(x^y\) 与\(y!\)的大小. 输入格式 第一行一个整数\(T\)表示数据组数. 接下来\(T\)行,每行两个整数\( ...
- [火星补锅] 水题大战Vol.2 T2 && luogu P3623 [APIO2008]免费道路 题解
前言: 如果我自己写的话,或许能想出来正解,但是多半会因为整不出正确性而弃掉. 解析: 这题算是对Kruskal的熟练运用吧. 要求一颗生成树.也就是说,最后的边数是确定的. 首先我们容易想到一个策略 ...
- [火星补锅] 水题大战Vol.2 T1 && luogu P1904 天际线 题解 (线段树)
前言: 当时考场上并没有想出来...后来也是看了题解才明白 解析: 大家(除了我)都知道,奇点和偶点会成对出现,而出现的前提就是建筑的高度突然发生变化.(这个性质挺重要的,我之前没看出来) 所以就可以 ...
- MathExam小学一二年级计算题生成器V1.0
MathExam小学一二年级计算题生成器v1.0 一.预估与实际 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning ...
随机推荐
- css:实现文本两行或多行文本溢出显示省略号
div{ display: -webkit-box; -webkit-box-orient: vertical; word-break: break-all; word-wrap: break-wor ...
- 一款直击痛点的优秀http框架,让我超高效率完成了和第三方接口的对接
1.背景 因为业务关系,要和许多不同第三方公司进行对接.这些服务商都提供基于http的api.但是每家公司提供api具体细节差别很大.有的基于RESTFUL规范,有的基于传统的http规范:有的需要在 ...
- Ubuntu Server 19.04配置静态IP
这个/etc/netplan下默认有个文件50-cloud-init.yaml,直接修改它就行了 sudo vim /etc/netplan/50-cloud-init.yaml 网口名字enp0s3 ...
- vue的自定义指令。directive
在vue中有很多vue自带的指令,比如v-heml.v-for.v-if,v-on.v-bind.v-else.v-show. 但是这些指令还不够我们使用的.就有了directive这个对象. 这个使 ...
- [难题题解] [BZOJ1875] [SDOI2009] HH去散步
题目H有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因为HH是个喜欢变化的人 ...
- Dom运用2
1.登录系统 <!--输入框创建--> 账号:<input class="ipt" type="text"><br> 密码: ...
- 解释Crypto模块,No module named "Crypto"
1.pip install pycryptodome 2.Python\Python38\Lib\site-packages,找到这个路径,下面有一个文件夹叫做crypto,将小写c改成大写C就ok了 ...
- setTimeout、clearTimeout、setInterval
setTimeout(cb, ms) setTimeout(cb, ms) 全局函数在指定的毫秒(ms)数后执行指定函数(cb).:setTimeout() 只执行一次指定函数. 返回一个代表定时器的 ...
- Python os.minor() 方法
概述 os.minor() 方法用于从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field ).高佣联盟 www.cgewang.com 语法 minor ...
- 原生JS 实现点击按钮创建元素
要求: 点击按钮,随机生成一个20px-100px宽度正方形,随机颜色,随机位置,不能出可视区域外 思路:(1)创建按钮,为按钮添加事件侦听 (2)触发事件,创建一个元素 (3)设置元素样式,包括大小 ...