题目描述

喜欢数学的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. layui 获取select option value 获取text

    $.trim($("#processState").val()): //获取val $("#processState option:selected").tex ...

  2. Vue中 v-bind和v-on 缩写

    v-bind 缩写 <!-- 完整语法 --> <a v-bind:href="url">...</a> <!-- 缩写 --> & ...

  3. 微信 JS-SDK 各种问题记录

    在开发微信公众号网页中,使用微信的 JS-SDK 会遇到各种坑.记录遇到的坑及解决方法. 1.JS-SDK 配置(url 指向). 在 JS-SDK 配置中,配置的签名基本在服务器完成,网上有各种方法 ...

  4. ffmpeg精简编译

    项目上需要用到ffmpeg的接收功能,把rtp流转封装为ts吐udp组播流,不涉及编码,所以需要精简一下脚本如下: #!/bin/bash dir=$(pwd) echo $dir rm -rf $d ...

  5. mysq远程连接报错,host..

    在本机登入mysql后,更改"mysql"数据库里的"user"表里的"host"项,从"localhost"改为'%' ...

  6. heap和stack区别

    转载自博客:https://www.cnblogs.com/perfy/archive/2012/09/06/2672946.html 1.heap是堆 ,stack是栈 2.stack的空间由操作系 ...

  7. leetcode 125 验证回文字符串 Valid Palindrome

    验证回文字符串 C++ 思路就是先重新定义一个string ,先遍历第一遍,字符串统一小写,去除空格:然后遍历第二遍,首尾一一对应比较:时间复杂度O(n+n/2),空间O(n); class Solu ...

  8. lua 十进制转二进制

    -- Converts a byte to a string of 0s and 1s. function byte2bin(n) local t = {} for i=7,0,-1 do t[#t+ ...

  9. PHP 验证香港身份证ID号

    /**check hk idcard$id = "K548653A";$xx= check_hkid($id);var_dump($xx);**/function check_hk ...

  10. JavaScript —— 用法 输出

    用法 必须在<script>标签内 可以在<body>和<head>部分中 不限数量 <script> ... </script> 即可,不 ...