题目描述

喜欢数学的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)的更多相关文章

  1. 2020 CCPC Wannafly Winter Camp Day1 C. 染色图

    2020 CCPC Wannafly Winter Camp Day1 C. 染色图 定义一张无向图 G=⟨V,E⟩ 是 k 可染色的当且仅当存在函数 f:V↦{1,2,⋯,k} 满足对于 G 中的任 ...

  2. 2020 CCPC Wannafly Winter Camp Day1 Div.1&amp F

    #include<bits/stdc++.h> #define forn(i, n) for (int i = 0; i < int(n); i++) #define fore(i, ...

  3. 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 ...

  4. CCPC Wannafly Winter Camp Div2 部分题解

    Day 1, Div 2, Prob. B - 吃豆豆 题目大意 wls有一个\(n\)行\(m\)列的棋盘,对于第\(i\)行第\(j\)列的格子,每过\(T[i][j]\)秒会在上面出现一个糖果, ...

  5. 2020 CCPC Wannafly Winter Camp Day2-K-破忒头的匿名信

    题目传送门 sol:先通过AC自动机构建字典,用$dp[i]$表示长串前$i$位的最小代价,若有一个单词$s$是长串的前$i$项的后缀,那么可以用$dp[i - len(s)] + val(s)$转移 ...

  6. 2020 CCPC Wannafly Winter Camp Day1-F-乘法

    题目传送门 sol:二分答案$K$,算大于$K$的乘积有多少个.关键在于怎么算这个个数,官方题解上给出的复杂度是$O(nlogn)$,那么计算个数的复杂度是$O(n)$的.感觉写着有点困难,自己写了一 ...

  7. 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 ...

  8. 2019 wannafly winter camp day 3

    2019 wannafly winter camp day 3 J 操作S等价于将S串取反,然后依次遍历取反后的串,每次加入新字符a,当前的串是T,那么这次操作之后的串就是TaT.这是第一次转化. 涉 ...

  9. 2019 wannafly winter camp day1-4代码库

    目录 day1 F div1 爬爬爬山 (最短路) B div2 吃豆豆 (dp) J div2 夺宝奇兵(暴力) J div1 夺宝奇兵 (权值线段树) C div1 拆拆拆数 E div1 流流流 ...

随机推荐

  1. Mybaits二级缓存的使用与配置

    什么是延迟加载  resultMap中的association和collection标签具有延迟加载的功能. 延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息.使用关联信息时再去加载关联信 ...

  2. P1309 瑞士轮 (吸氧了)

    P1309 瑞士轮 题解 1.这题可以模拟一下 2.sort吸氧可以过(可能是排序有点慢吧,不开会T) sort排序时注意: return 1 是满足条件,不交换 return 0是不满足,交换 代码 ...

  3. Windows操作路由表

    route print route add 172.17.0.0 mask 255.255.0.0 192.168.99.100 route delete 172.17.0.0 mask 255.25 ...

  4. CircleCI 前端自动部署

    概述 现在很多前端库都用到了 CircleCI 进行自动部署,比如Vue,React,作为一个前端我觉得还是有必要实操一下 CircleCI 的,总体来说还是挺简单的,我把过程和体会记录下来,供以后开 ...

  5. 编写Python脚本把sqlAlchemy对象转换成dict的教程

    编写Python脚本把sqlAlchemy对象转换成dict的教程 在用sqlAlchemy写web应用的时候,经常会用json进行通信,跟json最接近的对象就是dict,有时候操作dict也会比操 ...

  6. WIN10重启后,在任务栏下添加快捷工具栏消失问题修复

    WIN10重启后,在任务栏下添加快捷工具栏消失问题修复 可以在windows 设置 - - 设备 - - 输入 - - 高级键盘设置 - - 不要勾选 <使用桌面语言栏(如果可用 )>

  7. ARTS挑战

    最近有点迷茫,感觉自己工作了一年多,技术成长有限,我要做出改变.2019年11月2日,就从今天开始,参加耗子叔的ARTS挑战. ARTS的初衷 Algorithm:主要是为了编程训练和学习.每周至少做 ...

  8. idea中创建maven格式的文件方法

    其中新建的maven工程有时候不全或者出一些小问题导致新建类,或者其他文件时候找不到新建的快捷方式,下面就说一种快速设置

  9. 数据结构系列之2-3-4树的插入、查找、删除和遍历完整版源代码实现与分析(dart语言实现)

    本文属于原创,转载请注明来源. 在上一篇博文中,详细介绍了2-3树的操作(具体地址:https://www.cnblogs.com/outerspace/p/10861488.html),那么对于更多 ...

  10. & 和 && 区别和联系,| 和 || 区别和联系

    & 和 && 区别和联系,| 和 || 区别和联系,实际项目中,什么情况用哪种? 首先,& 和 && 的联系(共同点): & 和 &&a ...