【NOIP2018提高组D2T3】保卫王国

本博客介绍了NOIP2018提高组的一道题目,题目要求在树形结构中选择节点以覆盖所有边,并给出最小代价。解题思路涉及树上动态规划和线段树的应用。通过朴素的DP方法可以得到部分分数,对于限制两个点的情况,利用线段树维护状态并进行分类讨论。博主分享了具体的解决方案,包括换根操作和倍增算法在处理询问时的应用。
摘要由CSDN通过智能技术生成

题目大意

给定一棵树,每个点有一个权值。
每个点可以选或不选,但最后必须保证每一条边连着的两个点其中一个必选。
如果一个点选,那么就要付出该点权值的代价。
每一个询问,限制两个点必选还是必不选。然后输出最小代价和。
询问之间互相独立。
在这里插入图片描述

解题思路

当时在想的时候,已经想到了只限制一个点的做法,然后以为AC了,很开心。
可是由于失误,想到的分没有全都打。
朴素的dp可以拿44分。
对于数据类型2,直接按照只限制一个点的做法即可。
对于链,用线段树维护f,然后分类讨论一下即可。
对于B,直接暴力搞。
考虑到x的选取会对fa[x]有影响,所以:
g [ x ] [ 0 / 1 ] g[x][0/1] g[x][0/1]表示x不选/选,fa[x]的子树去掉x的子树的答案。
( h [ x ] [ 0 ] − f [ x ] [ 0 ] ) / ( h [ x ] [ 1 ] − f [ x ] [ 1 ] ) (h[x][0]-f[x][0])/(h[x][1]-f[x][1]) (h[x][0]f[x][0])/(h[x][1]f[x][1])表示x不选/选,整棵树去掉x的子树的答案。
计算h的时候通过换根操作求出即可。
G [ i ] [ x ] [ 0 / 1 ] [ 0 / 1 ] G[i][x][0/1][0/1] G[i][x][0/1][0/1]表示,去掉x的子树后,x到x的 2 i 2^i 2i祖先的链的g值和。其中x的 2 i 2^i 2i祖先不选/选,x不选/选。
另一种设法: G [ i ] [ x ] [ 0 / 1 ] [ 0 / 1 ] G[i][x][0/1][0/1] G[i][x][0/1][0/1]表示,去掉x的子树后,x到x的 2 i 2^i 2i祖先的链的g值和。其中x的 2 i − 1 2^i-1 2i1祖先不选/选,x不选/选。
这样的设法,导致合并信息的时候要讨论太多东西。
对于每个询问,考虑倍增。
a为a,b深度较大的那个。
令c=lca(a,b)
对于b=c,那么直接处理好a-b这条链,b两部分的信息。
只需要处理好a-c这条链,c,c-b这条链,b五部分的信息。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 100010
#define Min(x,y) ((x)<(y)?(x):(y))
#define Max(x,y) ((x)>(y)?(x):(y))
#define LL long long
#define Inf 100000000000
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
struct note{
   
	int to,next;
}edge[N<<1];
int head[N<<1],tot;
int i,j,k,l,n,m,cs;
LL ans,a0,a1;
int u,v,u2,v2,w;
int X,Y,W;
int a[N];
LL f[N][
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值