Codeforces Round #722 (Div. 2) C. Parsa‘s Humongous Tree(树形DP)

题目地址

题意

给你一棵树,树上的每一个点都有一个值区间,让你求树上相邻各点的值之差的最大值

输入

前n行是1~n的各个点的值区间
之后n-1行表示哪两个点之间是链接的

思路

首先,区间是没有用的,只可能取端点的值;
以下为证明:
设区间为l,r;
不取端点l,r,任取一点mid,使得l<mid<r;
再设在区间 [l,r] 左端有p个点,右段有q个点,
令p>q;显而易见用r代替mid时各点差的和更大,
p<q时同理可证,所以我使用 dp[x][2]来表示x为顶点取左右端点的最大值
给出状态转移方程:

        dp[x][0] += 1ll * max(dp[y][0] + abs(l[x] - l[y]), dp[y][1] + abs(l[x] - r[y]));
        dp[x][1] += 1ll * max(dp[y][0] + abs(r[x] - l[y]), dp[y][1] + abs(r[x] - r[y]));

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll tot=0,head[400007],ver[800007],nextt[800007],l[400007],r[400007],dp[400007][2];
void add(int x,int y)//加点
{
    tot++;
    ver[tot]=y;
    nextt[tot]=head[x];
    head[x]=tot;
}
void dfs(int x,int pre)//dfs
{
    for(int i=head[x]; i; i=nextt[i])
    {
        int y=ver[i];
        if(y==pre)
            continue;
        dfs(y,x);
        dp[x][0] += 1ll * max(dp[y][0] + abs(l[x] - l[y]), dp[y][1] + abs(l[x] - r[y]));
        dp[x][1] += 1ll * max(dp[y][0] + abs(r[x] - l[y]), dp[y][1] + abs(r[x] - r[y]));
    }
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
    	tot=0;
        int n;
        cin>>n;
        for(int i=1; i<=n; i++)
        {
            scanf("%lld %lld",&l[i],&r[i]);
            dp[i][0]=0;
            dp[i][1]=0;
            head[i]=0;
        }
        for(int i=1;i<=n-1;i++)
        {
        	int p,q;
        	scanf("%d %d",&p,&q);
        	add(p,q);
        	add(q,p);//正反加
		}
		dfs(1,0);
		cout<<max(dp[1][0],dp[1][1])<<endl;
    }
}

一点吐槽

在这里插入图片描述
考试的时候TLE4是因为用了cin没用scanf,第一次被这东西卡到,结果那场D做出来了C没做出来。。感觉看到大输入的时候就要有意识的换输入方式了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值