题目描述

设一个n个节点的二叉树tree的中序遍历为(1,2,3,…,n),其中数字1,2,3,…,n为节点编号。每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下:

subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数。

若某个子树为空,规定其加分为1,叶子的加分就是叶节点本身的分数。不考虑它的空子树。

试求一棵符合中序遍历为(1,2,3,…,n)且加分最高的二叉树tree。要求输出;

(1)tree的最高加分

(2)tree的前序遍历

输入输出格式

输入格式:

第1行:一个整数n(n<30),为节点个数。

第2行:n个用空格隔开的整数,为每个节点的分数(分数<100)。

输出格式:

第1行:一个整数,为最高加分(结果不会超过4,000,000,000)。

第2行:n个用空格隔开的整数,为该树的前序遍历。

输入输出样例

输入样例#1

5

5 7 1 2 10

输出样例#1

145

3 1 2 4 5

算法:

区间DP

 

分析:

这个10多年前的提高组试题其实也不算太难,但是有很多要注意的小点。

首先这道题上手先分析感觉和树形DP有点关系,然而再看清楚一点呢,就发现它其实只是在区间上dp,然而树只是对它的一个约束。

我们先来简化题目,假如我问的是在一个区间上求最大加分,那么这个状态转移方程应该很容易得到,就是f[i][j]=max(f[i][k-1]*f[k+1][j]+a[k])其中表示从i到j的区间最大值,k满足i<=k<=j。

注意这里可以取等。

 

接下来,有一个性质:

对于任意二叉树,其中序遍历中的任意一段区间的根节点可以是任何一个节点。

 

那么问题解决。

 

这个就可以直接套用到区间DP中,不过还要记录下相应的i,j的根节点是什么。最后输出先序遍历的过程其实就是dfs的思想,加一个记忆化搜索会提高效率。

 

要点注意:

1、为了方便调试,可以将数组开到6,但注意要调回正常值在提交

2、存答案的数组要用long long,否则会wa

3、记忆化部分要确定有值(非空子树)才递归下去

4、初始化答案数组f要放在输入前

5、注意要先定好某次递推的区间长度,否则会找到没运算过的值。

上代码:

 #include<cstdio>
#include<iostream>
using namespace std; long long f[][]; //注意要用超长整型
int n,r[][],a[],fl=; inline int read()
{
int x=,f=;
char c=getchar();
while (c<||c>)
f=c=='-'?-:,c=getchar();
while (c>=&&c<=)
x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
} void tree(int lt,int rt)
{
if (r[lt][rt]) //某些oj会判结尾为空格的情况
{
if (!fl)
printf("%d",r[lt][rt]),fl=;
else
printf(" %d",r[lt][rt]);
}
if (r[lt][r[lt][rt]-]) //递归左子树
tree(lt,r[lt][rt]-);
if (r[r[lt][rt]+][rt]) //递归右子树
tree(r[lt][rt]+,rt);
} int main()
{
int i,j,k,len;
n=read();
for (i=;i<=n;i++) //初始化为1,注意不可以memset
for (j=;j<=n;j++)
f[i][j]=;
for (i=;i<=n;i++)
{
a[i]=read();
f[i][i]=a[i]; //每个点自己作为叶子节点时,
r[i][i]=i; //根节点就是自己
}
/* //注意这种方法不可取
for (i=1;i<=n-1;i++)
for (j=i+1;j<=n;j++)
{
long long tmp=INF;
for (k=i;k<=j;k++)
if (tmp<f[i][k-1]*f[k+1][j]+a[k])
{
tmp=f[i][k-1]*f[k+1][j]+a[k];
r[i][j]=k;
}
f[i][j]=tmp;
}
*/
for (len=;len<=n;len++) //先定区间长度
for (i=;i+len<=n;i++) //设起点,i+len为终点
{
long long tmp=-; //没必要太小
for (k=i;k<=i+len;k++) //寻根
if (tmp<f[i][k-]*f[k+][i+len]+a[k])
{
tmp=f[i][k-]*f[k+][i+len]+a[k];
r[i][i+len]=k;
}
f[i][i+len]=tmp;
}
printf("%lld\n",f[][n]);
tree(,n);
return ;
}

讲讲memset为什么不行,因为在c++中memset是按位来赋值的,一个int是4位,一个long long是8位(好像是吧),所以一次就会推了8个1,而不是想要的一个1。而对于清零和赋极值memset是很好用的。

 

嗯,就这样了。

【NOIP2013提高组T3】加分二叉树的更多相关文章

  1. 【NOIP2003提高组】加分二叉树

    https://www.luogu.org/problem/show?pid=1040 令f(i,j)表示[i,j]的二叉树中最高的分数.枚举k为根,状转方程:f(i,j)=max{f(i,k-1)* ...

  2. [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路

    [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路 题目大意: 对于长度为\(n(n\le10^5)\)的非负数列\(A\),每次可以选取一个区间\(-1\).问将数列清零至少需要 ...

  3. JZOJ2020年8月11日提高组T3 页

    JZOJ2020年8月11日提高组T3 页 题目 Description 战神阿瑞斯听说2008年在中华大地上,将举行一届规模盛大的奥林匹克运动会,心中顿觉异常兴奋,他想让天马在广阔的天空上,举行一场 ...

  4. 【GDKOI2014】JZOJ2020年8月13日提高组T3 壕壕的寒假作业

    [GDKOI2014]JZOJ2020年8月13日提高组T3 壕壕的寒假作业 题目 Description Input Output 输出n行.第i行输出两个整数,分别表示第i份作业最早完成的时刻以及 ...

  5. JZOJ2020年8月10日提高组T3 玩诈欺的小杉

    JZOJ2020年8月10日提高组T3 玩诈欺的小杉 题目 Description 是这样的,在小杉的面前有一个N行M列的棋盘,棋盘上有\(N*M\)个有黑白棋的棋子(一面为黑,一面为白),一开始都是 ...

  6. 【佛山市选2013】JZOJ2020年8月7日提高组T3 海明距离

    [佛山市选2013]JZOJ2020年8月7日提高组T3 海明距离 题目 描述 对于二进制串a,b,他们之间的海明距离是指两个串异或之后串中1的个数.异或的规则为: 0 XOR 0 = 0 1 XOR ...

  7. 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行

    [NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...

  8. [NOIP2013 提高组] 华容道 P1979 洛谷

    [NOIP2013 提高组] 华容道 P1979 洛谷 强烈推荐,更好的阅读体验 经典题目:spfa+bfs+转化 题目大意: 给出一个01网格图,和点坐标x,y空格坐标a,b,目标位置tx,ty要求 ...

  9. [NOIP2013提高组] CODEVS 3287 火车运输(MST+LCA)

    一开始觉得是网络流..仔细一看应该是最短路,再看数据范围..呵呵不会写...这道题是最大生成树+最近公共祖先.第一次写..表示各种乱.. 因为要求运输货物质量最大,所以路径一定是在最大生成树上的.然后 ...

随机推荐

  1. PHP中关于取模运算及符号

    执行程序段<?php  echo 8%(-2) ?>,输出结果是: %为取模运算,以上程序将输出0 $a%$b,其结果的正负取决于$a的符号. echo ((-8)%3);     //将 ...

  2. web三大组件的加载顺序

    Web三大组件:过滤器组件  监听器组件  Servlet组件 过滤器的顶级接口:javax.servlet.Filter 监听器的顶级接口:javax.servlet.ServletContextL ...

  3. kafka 基础知识梳理-kafka是一种高吞吐量的分布式发布订阅消息系统

    一.kafka 简介 今社会各种应用系统诸如商业.社交.搜索.浏览等像信息工厂一样不断的生产出各种信息,在大数据时代,我们面临如下几个挑战: 如何收集这些巨大的信息 如何分析它 如何及时做到如上两点 ...

  4. Netty系列学习

    Netty系列之Netty高性能之道 Netty系列之Netty线程模型 Netty系列之Netty 服务端创建 Netty系列之Netty编解码框架分析 Netty系列之Netty百万级推送服务设计 ...

  5. [LeetCode] Search in Rotated Array II

    Follow up for "Search in Rotated Sorted Array":What if duplicates are allowed? Would this ...

  6. python获取toast 验证

    appium版本 1.6.3  desired_caps['automationName']='uiautomator2'    def _find_toast(self,message,timeou ...

  7. 图解用HTML5的popstate如何玩转浏览器历史记录

    一.popstate用来做什么的?简而言之就是HTML5新增的用来控制浏览器历史记录的api. 二.过去如何操纵浏览器历史记录? window.history对象,该对象上包含有length和stat ...

  8. 第139天:详解cookie、 sessionStorage 和localStorage

    1.cookie:存储在用户本地终端上的数据.有时也用cookies,指某些网站为了辨别用户身份,进行session跟踪而存储在本地终端上的数据,通常经过加密.一般应用最典型的案列就是判断注册用户是否 ...

  9. solr源码分析之searchComponent

    上文solr源码分析之数据导入DataImporter追溯中提到了solr的工作流程,其核心是各种handler. handler定义了各种search Component, @Override pu ...

  10. 洛谷 P1495 曹冲养猪

    这是一道标准的孙子定理的题,题意浅显,思路明确 然后我就交了整整16遍啊,欺负人啊,题解暴力就能过,我就TLE ..悲惨的提交记录 下面是题面 题目描述 自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干 ...