CCPC-Wannafly Winter Camp Day1 流流流动 (树形dp)
题目描述
喜欢数学的wlswls最近被萎住了。
现在他一共有1...n1...n这么多数字,取数字ii会得到f[i]f[i]的收益。数字之间有些边,对于所有的i(i != 1)i(i!=1),若ii为奇数,则ii与3i+13i+1之间有边,否则ii与i/2i/2之间有边。如果一条边的两个顶点xyxy都被取了,那么会失去d[min(x, y)]d[min(x,y)]的价值。请问wlswls怎么取,才能使得收益最大?
输入描述
第一行一个整数nn。
接下来一行nn个整数表示ff。
接下来一行nn个整数表示dd。
1 \leq n \leq 1001≤n≤100
1 \leq f[i], d[i] \leq 10001≤f[i],d[i]≤1000
输出描述
输出一个整数表示答案。
样例输入 1
2
10 10
1 2
样例输出 1
19 思路:
根据题目给的建边条件,建边后会形成一个森林,然后把森林转化为一个0为根节点的树,随后进行树形dp。
定义状态:
dp[u][0/1] 0为 第u个节点的子树中不取第u个节点的最多利益值,
1为第u个节点的子树中取第u个节点的最多利益值,
常规的树形dp套路,
dp[u][0]+=max(dp[v][0],dp[v][1]);
dp[u][1]+=max(dp[v][0],dp[v][1]-d[min(u,v)]);// 一个边上两个节点都取的话,要减去对应的值。
最后max(dp[0][0],dp[0][1])就是我们的答案值。
细节见代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = ; while (b) {if (b % )ans = ans * a % MOD; a = a * a % MOD; b /= ;} return ans;}
inline void getInt(int* p);
const int maxn = ;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/ int pre[maxn];
int f[maxn];
int d[maxn];
int dp[maxn][];
int n;
int findpar(int x)
{
return pre[x] == ? x : pre[x] = findpar(pre[x]);
}
void mer(int x, int y)
{
x = findpar(x);
y = findpar(y);
if (x != y)
{
pre[x] = y;
}
}
std::vector<int> v[maxn];
int w;
void dfs(int u, int pre)
{
// cout<<u<<" "<<pre<<endl;
dp[u][] = ;
dp[u][] = f[u];
for (auto x : v[u])
{
if (x != pre)
{
dfs(x, u);
dp[u][] += max(dp[x][], dp[x][]);
dp[u][] += max(dp[x][], dp[x][] - d[min(u, x)]);
}
}
}
int main()
{
//freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
//freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);
gbtb;
cin >> n;
repd(i, , n)
{
cin >> f[i];
}
repd(i, , n)
{
cin >> d[i];
}
repd(i, , n)
{
if (i & )
{
if ( * i + <= n)
{
v[i].push_back( * i + );
v[ * i + ].push_back(i);
mer(i, * i + );
}
} else
{
v[i].push_back(i / );
v[i / ].push_back(i);
mer(i, i / );
}
}
repd(i, , n)
{
if (pre[i] == )
{
v[].push_back(i);
v[i].push_back();
}
}
dfs(, );
cout << max(dp[][], dp[][]) << endl; return ;
} inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '');
while ((ch = getchar()) >= '' && ch <= '') {
*p = *p * - ch + '';
}
}
else {
*p = ch - '';
while ((ch = getchar()) >= '' && ch <= '') {
*p = *p * + ch - '';
}
}
}
CCPC-Wannafly Winter Camp Day1 流流流动 (树形dp)的更多相关文章
- 2020 CCPC Wannafly Winter Camp Day1 C. 染色图
2020 CCPC Wannafly Winter Camp Day1 C. 染色图 定义一张无向图 G=⟨V,E⟩ 是 k 可染色的当且仅当存在函数 f:V↦{1,2,⋯,k} 满足对于 G 中的任 ...
- 2020 CCPC Wannafly Winter Camp Day1 Div.1& F
#include<bits/stdc++.h> #define forn(i, n) for (int i = 0; i < int(n); i++) #define fore(i, ...
- 2020 CCPC Wannafly Winter Camp Day1 - I. K小数查询(分块)
题目链接:K小数查询 题意:给你一个长度为$n$序列$A$,有$m$个操作,操作分为两种: 输入$x,y,c$,表示对$i\in[x,y] $,令$A_{i}=min(A_{i},c)$ 输入$x,y ...
- CCPC Wannafly Winter Camp Div2 部分题解
Day 1, Div 2, Prob. B - 吃豆豆 题目大意 wls有一个\(n\)行\(m\)列的棋盘,对于第\(i\)行第\(j\)列的格子,每过\(T[i][j]\)秒会在上面出现一个糖果, ...
- 2020 CCPC Wannafly Winter Camp Day2-K-破忒头的匿名信
题目传送门 sol:先通过AC自动机构建字典,用$dp[i]$表示长串前$i$位的最小代价,若有一个单词$s$是长串的前$i$项的后缀,那么可以用$dp[i - len(s)] + val(s)$转移 ...
- 2020 CCPC Wannafly Winter Camp Day1-F-乘法
题目传送门 sol:二分答案$K$,算大于$K$的乘积有多少个.关键在于怎么算这个个数,官方题解上给出的复杂度是$O(nlogn)$,那么计算个数的复杂度是$O(n)$的.感觉写着有点困难,自己写了一 ...
- 2019 wannafly winter camp
2019 wannafly winter camp Name Rank Solved A B C D E F G H I J K day1 9 5/11 O O O O O day2 5 3/11 O ...
- 2019 wannafly winter camp day 3
2019 wannafly winter camp day 3 J 操作S等价于将S串取反,然后依次遍历取反后的串,每次加入新字符a,当前的串是T,那么这次操作之后的串就是TaT.这是第一次转化. 涉 ...
- 2019 wannafly winter camp day1-4代码库
目录 day1 F div1 爬爬爬山 (最短路) B div2 吃豆豆 (dp) J div2 夺宝奇兵(暴力) J div1 夺宝奇兵 (权值线段树) C div1 拆拆拆数 E div1 流流流 ...
随机推荐
- 【Spark机器学习速成宝典】基础篇03数据读取与保存(Python版)
目录 保存为文本文件:saveAsTextFile 保存为json:saveAsTextFile 保存为SequenceFile:saveAsSequenceFile 读取hive 保存为文本文件:s ...
- Java synchronized到底锁住的是什么?
使用环境:多线程java程序中. 作用:在多线程的环境下,控制synchronized代码段不被多个线程同时执行.synchronized既可以加在一段代码上,也可以加在方法上. 使用:synchro ...
- Eigen中的矩阵及向量运算
Eigen中的矩阵及向量运算 ,[+,+=,-,-=] ,[\*,\*=] ,[.transpose()] ,[.dot(),.cross(),.adjoint()] ,针对矩阵元素进行的操作[.su ...
- 浏览器端-W3School:JS & DOM 参考手册
ylbtech-浏览器端-W3School:JS & DOM 参考手册 1.返回顶部 1. JavaScript 参考手册 本部分提供完整的 JavaScript 参考手册: JavaScri ...
- 【mysql】如何通过navicat配置表与表的多对一关系,一对一关系?设计外键的效果
背景: 现在要将接口自动化测试结果持久化,当前只是每次运行接口测试,将测试结果通过邮件发送给项目组成员.邮件内容如下: 表设计: 为了呈现这个结果:我设计了2张表run_result和run_deta ...
- Spring+hibernate 配置实例
转自:http://www.cnblogs.com/hongten/archive/2012/03/10/java_spring_hibernate.html 项目结构: http://www.cnb ...
- Linux_KVM虚拟机
目录 目录 Hpyervisor的种类 安装KVM 使用virsh指令管理虚拟机 KVM虚拟机的网络设置 Hpyervisor的种类 hpyervisor:是一种VMM(Virtual Machine ...
- Linux_PXE服务器_RHEL7
目录 目录 前言 PXE原理 搭建PXE服务器 关闭SELinux和防火墙 配置DHCP 配置TFTP 配置FTP 配置Kickstart 前言 PXE(preboot execute environ ...
- MYSQL5.6源码包编译安装
linux下用cmake编译安装mysql-5.6.35cmake编译安装mysql的方法:#useradd -M mysql -s /sbin/nologin#yum install -y cmak ...
- Spring 初识
一.Spring是什么? 首先可以进入Spring官网 https://spring.io/ 看一下相关介绍. Spring为开发者提供了一站式的轻量级应用开发平台.简单来说,Spring为开发者提供 ...