题目描述

Alice和Bob有一棵树(无根、无向),在第i个点上有ai个巧克力。首先,两人个选择一个起点(不同的),获得点上的巧克力;接着两人轮流操作(Alice先),操作的定义是:在树上找一个两人都没选过的点并获得点上的巧克力,并且这个点要与自己上一次选的点相邻。当有一人无法操作 时,另一个人可以继续操作,直到不能操作为止。因为Alice和Bob是好朋友,所以他们希望两人得到的巧克力总和尽量大,请输出最大总和。

数据范围

对于20%的数据,n<=15

对于40%的数据,n<=100

对于60%的数据,n<=5000

对于100%的数据,n<=200000,0<=ai<=1000000000(1e9)

=w=

题目模型显然:寻找一棵树上的两条不相交的链使得权值和最大。

树形动态规划。

分两种情况讨论:

1.两条链靠近(存在一条树边,两个端点分居这两条链中);

2.两条链分居一个结点的两颗子树。

易推。

代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define ll long long
using namespace std;
const char* fin="aP2.in";
const char* fout="aP2.out";
const ll inf=0x7fffffff;
const ll maxn=200007,maxm=maxn*2;
ll n,i,j,k,maxx,mxid,ans;
ll a[maxn],fi[maxn],la[maxm],ne[maxm],tot;
ll f[maxn],g[maxn],st[maxn],pre[maxn],spre[maxn],suf[maxn],ssuf[maxn];
ll Pre[maxn],Suf[maxn];
ll h[maxn],h1[maxn];
bool ban[maxn],ok[maxn];
void add_line(ll a,ll b){
tot++;
ne[tot]=fi[a];
la[tot]=b;
fi[a]=tot;
}
void xdfs(ll v,ll from){
ll i,j,k,maxx,smaxx,tmp;
st[0]=0;
for (k=fi[v];k;k=ne[k]) if (la[k]!=from) st[++st[0]]=g[la[k]];
if (from) st[++st[0]]=h1[v];
maxx=smaxx=0;
for (i=1;i<=st[0];i++){
if (maxx<st[i]){
smaxx=maxx;
maxx=st[i];
}else smaxx=max(st[i],smaxx);
pre[i]=maxx;
spre[i]=smaxx;
}
suf[st[0]+1]=ssuf[st[0]+1]=0;
maxx=smaxx=0;
for (i=st[0];i;i--){
if (maxx<st[i]){
smaxx=maxx;
maxx=st[i];
}else smaxx=max(st[i],smaxx);
suf[i]=maxx;
ssuf[i]=smaxx;
}
tmp=0;
for (k=fi[v];k;k=ne[k]) if (la[k]!=from) {
tmp++;
i=max(pre[tmp-1],suf[tmp+1]);
j=max(min(pre[tmp-1],suf[tmp+1]),max(spre[tmp-1],ssuf[tmp+1]));
h1[la[k]]=i+a[v];
h[la[k]]=a[v]+i+j;
}
for (k=fi[v];k;k=ne[k]) if (la[k]!=from) xdfs(la[k],v);
ans=max(ans,h[v]+f[v]);
}
void dfs(ll v,ll from){
ll i,j,k,maxx,smaxx,tmp;
g[v]=a[v];
for (k=fi[v];k;k=ne[k]){
if (la[k]!=from){
dfs(la[k],v);
g[v]=max(g[v],g[la[k]]+a[v]);
f[v]=max(f[v],f[la[k]]);
}
}
st[0]=0;
for (k=fi[v];k;k=ne[k]) if (la[k]!=from) st[++st[0]]=la[k];
maxx=smaxx=0;
for (i=1;i<=st[0];i++){
if (maxx<g[st[i]]){
smaxx=maxx;
maxx=g[st[i]];
}else smaxx=max(g[st[i]],smaxx);
pre[i]=maxx;
spre[i]=smaxx;
Pre[i]=max(Pre[i-1],f[st[i]]);
}
Suf[st[0]+1]=suf[st[0]+1]=ssuf[st[0]+1]=0;
maxx=smaxx=0;
for (i=st[0];i;i--){
if (maxx<g[st[i]]){
smaxx=maxx;
maxx=g[st[i]];
}else smaxx=max(g[st[i]],smaxx);
suf[i]=maxx;
ssuf[i]=smaxx;
Suf[i]=max(Suf[i+1],f[st[i]]);
}
f[v]=max(f[v],maxx+smaxx+a[v]);
tmp=0;
for (k=fi[v];k;k=ne[k])
if (la[k]!=from){
tmp++;
i=max(pre[tmp-1],suf[tmp+1]);
j=max(min(pre[tmp-1],suf[tmp+1]),max(spre[tmp-1],ssuf[tmp+1]));
ans=max(ans,f[la[k]]+i+j+a[v]);
ans=max(ans,f[la[k]]+max(Pre[tmp-1],Suf[tmp+1]));
}
}
int main(){
scanf("%lld",&n);
for (i=1;i<=n;i++) scanf("%lld",&a[i]);
for (i=1;i<n;i++){
scanf("%lld%lld",&j,&k);
add_line(j,k);
add_line(k,j);
}
dfs(1,0);
xdfs(1,0);
printf("%lld",ans);
return 0;
}

=o=

求最大值和次大值,可以维护三大边。

不用像我维护什么前缀最大值,和后缀最大值= =

【JZOJ4923】【NOIP2017提高组模拟12.17】巧克力狂欢的更多相关文章

  1. 求hack or 证明(【JZOJ 4923】 【NOIP2017提高组模拟12.17】巧克力狂欢)

    前言 本人在此题有一种不是题解的方法,但无法证明也找不到反例. 如果各位大神有反例或证明请发至 邮箱:qq1350742779@163.com Description Alice和Bob有一棵树(无根 ...

  2. 【NOIP2017提高组模拟12.17】环

    题目 小A有一个环,环上有n个正整数.他有特殊的能力,能将环切成k段,每段包含一个或者多个数字.对于一个切分方案,小A将以如下方式计算优美程度: 首先对于每一段,求出他们的数字和.然后对于每段的和,求 ...

  3. 【JZOJ4922】【NOIP2017提高组模拟12.17】环

    题目描述 小A有一个环,环上有n个正整数.他有特殊的能力,能将环切成k段,每段包含一个或者多个数字.对于一个切分方案,小A将以如下方式计算优美程度: 首先对于每一段,求出他们的数字和.然后对于每段的和 ...

  4. 【JZOJ4924】【NOIP2017提高组模拟12.17】向再见说再见

    题目描述 数据范围 =w= 设h[i]表示,甲队得到i分的方案数. 那么h[(n+k)/2]和h[(n−k)/2]就是答案. 设g[i]表示,甲队得到至少i分的方案数. 那么h[i]=g[i]−∑j& ...

  5. 【NOIP2017提高组模拟12.24】B

    题目 现在你有N个数,分别为A1,A2,-,AN,现在有M组询问需要你回答.每个询问将会给你一个L和R(L<=R),保证Max{Ai}-Min{Ai}<=R-L,你需要找出并输出最小的K( ...

  6. 【NOIP2017提高组模拟12.10】幻魔皇

    题目 幻魔皇拉比艾尔很喜欢斐波那契树,他想找到神奇的节点对. 所谓斐波那契树,根是一个白色节点,每个白色节点都有一个黑色节点儿子,而每个黑色节点则有一个白色和一个黑色节点儿子.神奇的节点对则是指白色节 ...

  7. 【NOIP2017提高组模拟12.10】神炎皇

    题目 神炎皇乌利亚很喜欢数对,他想找到神奇的数对. 对于一个整数对(a,b),若满足a+b<=n且a+b是ab的因子,则成为神奇的数对.请问这样的数对共有多少呢? 分析 设\(gcd(a,b)= ...

  8. 【JZOJ4930】【NOIP2017提高组模拟12.18】C

    题目描述 给出一个H的行和W列的网格.第i行第j列的状态是由一个字母的A[i][j]表示,如下: "." 此格为空. "o" 此格包含一个机器人. " ...

  9. 【JZOJ4929】【NOIP2017提高组模拟12.18】B

    题目描述 在两个n*m的网格上染色,每个网格中被染色的格子必须是一个四联通块(没有任何格子被染色也可以),四联通块是指所有染了色的格子可以通过网格的边联通,现在给出哪些格子在两个网格上都被染色了,保证 ...

随机推荐

  1. 基于 Kubernetes 实践弹性的 CI/CD 系统

    大家好,我是来自阿里云容器服务团队的华相.首先简单解释一下何为 Kubernetes 来帮助大家理解.Kuberentes 是一个生产可用的容器编排系统.Kuberentes 一方面在集群中把所有 N ...

  2. Ionic JPush极光推送二

    1.看图解决问题   2.解决出现统计代码提示问题 修改这个java 文件 导入命名空间 import cn.jpush.android.api.JPushInterface; 添加方法 @Overr ...

  3. Django项目:CRM(客户关系管理系统)--77--67PerfectCRM实现CRM课程出勤排名

    # classtop_urls.py # ————————64PerfectCRM实现CRM课程排名详情———————— from django.conf.urls import url from b ...

  4. 提交代码出现 Push to origin/master was rejected 错误解决方法

    转至博客:http://www.xtyos.cn/archives/qt-1-index 为什么会出现这样的问题 一般发生在 GitHub 或 码云 刚刚创建仓库第一次pull的时候,两个仓库的差别非 ...

  5. 2019-8-31-dotnet-如何调试某个文件是哪个代码创建

    title author date CreateTime categories dotnet 如何调试某个文件是哪个代码创建 lindexi 2019-08-31 16:55:58 +0800 201 ...

  6. LA3029 City Game

    Bob is a strategy game programming specialist. In his new city building game the gaming environment ...

  7. Leetcode105. Construct Binary Tree from Preorder and Inorder Traversal前序与中序构造二叉树

    根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15 ...

  8. Gym - 102163M

    Gym - 102163M https://vjudge.net/problem/2356949/origin取对数,然后特判特殊情况,就是0的那些情况 #include<iostream> ...

  9. http://codeforces.com/gym/100623/attachments H题

    http://codeforces.com/gym/100623/attachments H题已经给出来的,包括后来添加的,都累加得到ans,那么从1-ans都是可以凑出来的,如果ans<a[n ...

  10. 开发者说 | 分布式事务中间件 Seata 的设计原理

    导读 微服务架构体系下,我们可以按照业务模块分层设计,单独部署,减轻了服务部署压力,也解耦了业务的耦合,避免了应用逐渐变成一个庞然怪物,从而可以轻松扩展,在某些服务出现故障时也不会影响其它服务的正常运 ...