模拟赛 提米树 题解 (DP+思维)

题意:
有一棵棵提米树,满足这样的性质:
每个点上长了一定数量的Temmie 薄片,薄片数量记为这个点的权值,这些点被标记为 1 到 n 的整数,其
中 1 号点是树的根,没有孩子的点是树上的叶子。
定义\((a,b)\)是一对相邻的叶子,当且仅当没有其它的叶子节点在 DFS 序上在a,b 之间。
每对相邻的叶子都会产生一个代价,代价为 a 到 b 路径上(不包含 a,b)的点中,最大点权值。
提米树可以提供决心,一棵提米树能提供的决心的数量是树上所有叶子上长的 Temmie 薄片数量和,减去所有相邻叶子的代价。
Temmie 们决定对这棵树进行若干次剪枝(可以不剪枝),使得这棵树能提供的决心最多。
一次剪枝定义为:如果一个点的孩子都是叶子,就可以把它所有的孩子剪掉。

要求\(O(n)\)做法。

首先,考虑\(O(n^2)\)的60分暴力:
我们可以反过来:由根开始,每个节点考虑是否扩展出所有叶子。
若不扩展,则它的子树都是空的,它成为叶子。
我们可以在dfs序上DP:设\(dp(i,j)\)表示考虑到i,上一个叶子点为j的最大决心。
有两种转移:
1、若i不是叶子,可以扩展,转移到\(dp(i+1,j)\)。
2、可以不扩展,转移到\(dp(i+si_i,i)+w_i-max(i,j)\)。
代码如下:

for(int i=tm-1;i>=0;i--)
{
    for(int j=0;j<=n;j++)
    {
        int u=xl[i];
        dp[i][j]=dp[i+si[u]][u]+sz[u]-zd[j][u];
        if(si[u]>1&&dp[i+1][j]>dp[i][j])
            dp[i][j]=dp[i+1][j];
    }
}
printf("%d",dp[0][0]);

考虑优化:首先,要把维度降下来。
设\(dp(i)\)表示i成为叶子后的最大决心。
枚举下一个使用2转移的位置,代码如下:

for(int i=tm;i>=0;i--)
{
    int u=xl[i];
    dp[i]=-999999999;
    for(int j=i+si[u];j<=tm+1;j++)
    {
        int t=dp[j]-zd[u][xl[j]];
        if(t>=dp[i])
            dp[i]=t;
        if(si[xl[j]]==1)//注意此处,非常关键。
            break;
    }
    dp[i]+=sz[u];
}
printf("%d",dp[0]);

继续优化:
我们发现,对于\(i\),\(i+si_i\)就是i的祖先节点中第一个有更右子节点的点。
而由于注释处的break,使得转移就是在\(i+si[u]\)处,一直向左走形成的链。
那么:

绿点对橙点有贡献。
那么,我们枚举红点lca,再枚举相邻的两个儿子,计算贡献。
先算出链上每个节点到lca的最大值。设为\(h\),那么,就是\(dp(u)=max(dp(v)-max(h(u),h(v)))+w(u)\)。
由于h具有单调性,因此分\(h(u)>h(v)\)和\(h(u)<=h(v)\)进行讨论,提前算出链上\(dp\),以及\(dp-h\)的最大值。
这两种情况符合的v一定是前缀/后缀,双指针扫一下即可定位。

代码细节非常多。

#include <stdio.h>
#include <vector>
#define inf 999999999
using namespace std;
vector<int> ve[100010];
int sz[100010],cl[100010],cr[100010],dp[100010],zd[100010],fa[100010],ma[100010],md[100010];
int max(int a,int b)
{
    return a>b?a:b;
}
void dfs0(int u,int f)
{
    fa[u]=f;
    for(int i=0;i<ve[u].size();i++)
        dfs0(ve[u][i],u);
}
void dfs1(int u)
{
    for(int i=ve[u].size()-2;i>=0;i--)
    {
        dfs1(ve[u][i+1]);
        int t=ve[u][i],la=0;zd[u]=sz[u];
        while(t!=0)
        {
            zd[t]=max(sz[t],zd[fa[t]]);
            t=cr[t];
        }
        t=ve[u][i+1];
        while(t!=0)
        {
            zd[t]=max(sz[t],zd[fa[t]]);
            la=t;t=cl[t];
        }
        t=la;while(t!=u)
        {
            ma[t]=dp[t]-zd[fa[t]];
            if(cl[t])ma[t]=max(ma[t],ma[cl[t]]);
            t=fa[t];
        }
        t=ve[u][i+1];
        while(t!=0)
        {
            md[t]=dp[t];
            if(fa[t]!=u)md[t]=max(md[t],md[fa[t]]);
            t=cl[t];
        }
        ma[u]=md[u]=-inf;
        int x=ve[u][i],y=ve[u][i+1];
        while(x!=0)
        {
            while(y!=0&&zd[fa[y]]<zd[fa[x]])
                y=cl[y];
            if(y)
            {
                t=ma[y]+sz[x];
                if(t>dp[x])dp[x]=t;
            }
            t=md[(y==0?la:fa[y])]-zd[fa[x]]+sz[x];
            if(t>dp[x])dp[x]=t;x=cr[x];
        }
    }
    if(ve[u].size())dfs1(cl[u]);
}
int main()
{
    freopen("temmie.in","r",stdin);
    freopen("temmie.out","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int s,a;
        scanf("%d%d",&sz[i],&s);
        for(int j=0;j<s;j++)
        {
            scanf("%d",&a);
            ve[i].push_back(a);
        }
        if(s>0)
        {
            cl[i]=ve[i][0];
            cr[i]=ve[i][s-1];
        }
        dp[i]=-inf;
    }
    int u=1;
    while(u!=0)
    {
        dp[u]=sz[u];
        u=cr[u];
    }
    dfs0(1,0);dfs1(1);
    int ma=-inf;u=1;
    while(u!=0)
    {
        if(dp[u]>ma)
            ma=dp[u];
        u=cl[u];
    }
    printf("%d",ma);
    return 0;
}

原文地址:https://www.cnblogs.com/lnzwz/p/11637986.html

时间: 2024-10-03 23:04:48

模拟赛 提米树 题解 (DP+思维)的相关文章

4.9 省选模拟赛 圆圈游戏 树形dp set优化建图

由于圆不存在相交的关系 所以包容关系形成了树的形态 其实是一个森林 不过加一个0点 就变成了树. 考虑对于每个圆都求出最近的包容它的点 即他的父亲.然后树形dp即可.暴力建图n^2. const int MAXN=100010; int n,m,len; struct wy { ll x,y,r,w; inline int friend operator <(wy a,wy b){return a.r<b.r;} }t[MAXN]; int f[MAXN]; int lin[MAXN],ver

[noip模拟赛]某种数列问题&lt;dp&gt;

某种数列问题  (jx.cpp/c/pas) 1000MS 256MB 众所周知,chenzeyu97有无数的妹子(阿掉!>_<),而且他还有很多恶趣味的问题,继上次纠结于一排妹子的排法以后,今天他有非(chi)常(bao)认(cheng)真(zhe)去研究一个奇怪的问题.有一堆他的妹子站成一排,然后对于每个妹子有一个美丽度,当然美丽度越大越好,chenzeyu97妹子很多,但是质量上不容乐观,经常出现很多美丽度为负数的妹子(喜闻乐见),chenzeyu97希望从一排妹子里找出3队连续的妹子,

洛谷 U360 子矩阵 (NOIP模拟赛T1)题解

题目链接:https://www.luogu.org/problem/show?pid=U360 题目背景 夏令营 题目描述 小A有一个N×M的矩阵,矩阵中1~N*M这(N*M)个整数均出现过一次.现在小A在这个矩阵内选择一个子矩阵,其权值等于这个子矩阵中的所有数的最小值.小A想知道,如果他选择的子矩阵的权值为i(1<=i<=N×M),那么他选择的子矩阵可能有多少种?小A希望知道所有可能的i值对应的结果,但是这些结果太多了,他算不了,因此他向你求助. 输入输出格式 输入格式: 第一行,两个整数

【自创模拟赛】set1 题解

T2 本来想在 $T2$ 搞一道动态规划题,但现在好像不是了……出成了一道毒瘤结论题. 题目背景和板子啥的来源于我以前在luogu存的一道自创题. 100pts 这个点甚至卡 $O(n*log(n^2))$,而二分肯定是不能去掉的,所以我们考虑去掉链上对区间答案的维护的那一维 $log$. 我们重新分开考虑两个点的大小关系,以防混淆. 当祖先 $\lt M$,子孙 $\gt M$ 时, 我们发现,一次移动只有两个点的归属发生变化,橙点被加入可利用区域,红点被加入已分完区域. 所以 $place$

10.2模拟赛总结

10.2 模拟赛总结 T1. 数位dp: 一个非常非常非常非常显然的数位 DP \([L,R] = [1,R]-[1,L-1]\) 所以是分别求两次小于等于某个数字的方案数 \(f(i,j,k)\) 表示从低位数起的第 \(i\) 位,按照规则计算后答案为 \(j\quad (j=0,1)\) \(k\) 表示只考虑后面结尾和 \(lmt\)后面几位 的大小关系 \((k=0,1)\) 考虑第 \(i+1\) 位,算一下新构成的数字并判断下大小就可以了 注意到 \(L,R\) 数据范围特别大,需

[模拟赛10.12] 老大 (二分/树的直径/树形dp)

[模拟赛10.12] 老大 题目描述 因为 OB 今年拿下 4 块金牌,学校赞助扩建劳模办公室为劳模办公室群,为了体现 OI 的特色,办公室群被设计成了树形(n 个点 n ? 1 条边的无向连通图),由于新建的办公室太大以至于要将奖杯要分放在两个不同的地方以便同学们丢硬币进去开光,OB 想请你帮帮他看看奖杯放在哪两个办公室使得在任意一个在劳模办公室做题的小朋友能最快地找到奖杯来开光. 一句话题意:给出一个 n 个点的树,在两个合适且不同的点放上奖杯,使得每个点到最近的奖杯距离最大值最小. 输入

@省选模拟赛03/16 - T3@ 超级树

目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取一棵深度为 k 的满二叉树,对每个节点向它的所有祖先连边(如果这条边不存在的话). 例如,下面是一个 4-超级树: 请统计一棵 k-超级树 中有多少条不同的简单有向路径,对 mod 取模. input 一行两整数 k, mod. output 一行一整数表示答案. example input1: 2

lzoi模拟赛题解

A题:签到题原题:mtoi 联赛 的A题定位:真.签到题(普及B题或者提高d1A题)考点:选手的基本数学能力思维难度:提高-代码难度:普及A题 题解:80%:暴力枚举100%:注意到(a xor b)<=(a+b),于是把所有的数异或起来即可. B题:送分题原题:[多省省队联测]d2A:皮配定位:一道联赛d1B题,考察了选手的基本功.送了选手70分.把70%的2种做法扩展可以得到正解考点:多种背包dp,计数思维难度:提高代码难度:提高+ 前面的几个数据可以暴力枚举解决.50%的数据:考虑dp.设

10月15日模拟赛题解

10月15日模拟赛题解 A 树 Description 给定一棵 \(n\) 个节点的树,每个节点有两个参数 \(a,~b\),对于每个节点,求子树中参数为 \(b\) 的所有节点的 \(a\) 之和 Limitations \(100\%\) \(1 \leq b \leq n \leq 10^5,~a \leq 1000\) \(60\%\) \(1 \leq b,n\leq 1000\) \(30\%\) \(1 \leq b, n \leq 10\) Solution 对于 \(30\%