【Luogu】P4103大工程(虚树DP)
我貌似发现这类DP就是先别管什么虚树……把树形DP搞出来套上虚树板子就好了
这个树形DP就是设sum为答案,sumd为子树内所有点的深度和(当然指的是被询问的点),maxi指子树内最深的点的深度,mini同理
然后考虑我们dfs到x,它的儿子已经遍历到一半,新加进来一个儿子to
显然$sum[x]+=sum[to]+(sumd[x]-deep[x]*size[x])*size[to]+sumd[to]-deep[x]*size[to]$
$sumd+=sum[to]$
$maxi[x]=max(maxi[x],maxi[to])$
只要注意这类方程的先后顺序即可。
另外注意输出的先后顺序。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<algorithm>
#define maxn 1020020
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} long long sum[maxn],maxi[maxn],mini[maxn];
long long sumd[maxn];
long long ansa[maxn],ansb[maxn];
long long size[maxn]; long long dfn[maxn];
long long deep[maxn];
long long q[maxn];
long long stack[maxn],top;
long long s[maxn][];
bool vis[maxn];
long long ID; struct Pic{
struct Edge{
long long next,to;
}edge[maxn*];
long long head[maxn],num;
inline void add(long long from,long long to){
edge[++num]=(Edge){head[from],to};
head[from]=num;
}
void pre(long long x,long long fa){
dfn[x]=++ID; deep[x]=deep[fa]+;
for(long long i=head[x];i;i=edge[i].next){
long long to=edge[i].to;
if(to==fa) continue;
s[to][]=x;
pre(to,x);
}
return;
}
void dele(int x,int fa){
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(to==fa) continue;
dele(to,x);
}
head[x]=;
}
void dfs(long long x,long long fa){
sum[x]=maxi[x]=sumd[x]=size[x]=; ansa[x]=; ansb[x]=0x7fffffff;
mini[x]=0x7fffffff;
//printf("%lld %lld %lld %d>>>\n",sum[x],x);
for(long long i=head[x];i;i=edge[i].next){
long long to=edge[i].to;
if(to==fa) continue;
//printf("%d %d\n",x,to);
dfs(to,x);
if(maxi[x]) ansa[x]=max(ansa[x],maxi[x]+maxi[to]-*deep[x]);
if(mini[x]!=0x7fffffff) ansb[x]=min(ansb[x],mini[x]+mini[to]-*deep[x]);
maxi[x]=max(maxi[x],maxi[to]);
mini[x]=min(mini[x],mini[to]);
sum[x]+=sum[to];
//printf("%lld? %d????????\n",sum[x],x);
if(sumd[x]) sum[x]+=(sumd[x]-deep[x]*size[x])*size[to]+(sumd[to]-deep[x]*size[to])*size[x];
//printf("%lld %lld %d %d!!!!!!\n",sum[x],sumd[x],x,to);
size[x]+=size[to];
sumd[x]+=sumd[to];
ansa[x]=max(ansa[x],ansa[to]);
ansb[x]=min(ansb[x],ansb[to]);
}
if(vis[x]){
if(sumd[x]) sum[x]+=sumd[x]-(deep[x]*size[x]);
sumd[x]+=deep[x];
if(maxi[x]) ansa[x]=max(ansa[x],maxi[x]-deep[x]);
if(mini[x]!=0x7fffffff) ansb[x]=min(ansb[x],mini[x]-deep[x]);
maxi[x]=max(maxi[x],deep[x]);
mini[x]=min(mini[x],deep[x]);
size[x]++;
}
//printf("%lld %d\n",sum[x],x);
return;
}
}old,vir; bool cmp(long long a,long long b){ return dfn[a]<dfn[b]; } inline long long LCA(long long x,long long y){
if(deep[x]<deep[y]) swap(x,y);
long long f=deep[x]-deep[y];
for(long long i=;(<<i)<=f;++i)
if((<<i)&f) x=s[x][i];
if(x==y) return x;
for(long long i=;i>=;--i){
if(s[x][i]==s[y][i]) continue;
x=s[x][i];y=s[y][i];
}
return s[x][];
} int main(){
long long n=read();
for(long long i=;i<n;++i){
long long x=read(),y=read();
old.add(x,y); old.add(y,x);
}
old.pre(,);
for(long long j=;j<;++j)
for(long long i=;i<=n;++i) s[i][j]=s[s[i][j-]][j-];
long long m=read();
while(m--){
vir.num=top=;
long long e=read();
//printf("%d>>\n",e);
for(long long i=;i<=e;++i){
q[i]=read();
vis[q[i]]=;
// printf("%d>>>",dfn[q[i]]);
}
//printf("\n");
sort(q+,q+e+,cmp);
for(long long i=;i<=e;++i){
if(top==){
stack[++top]=q[i];
continue;
}
long long lca=LCA(q[i],stack[top]);
while(dfn[lca]<dfn[stack[top]]){
if(dfn[lca]>=dfn[stack[top-]]){
vir.add(lca,stack[top]);
if(stack[--top]!=lca) stack[++top]=lca;
break;
}
vir.add(stack[top-],stack[top]);
top--;
}
stack[++top]=q[i];
}
while(top>){
vir.add(stack[top-],stack[top]);
top--;
}
vir.dfs(stack[],stack[]);
printf("%lld %lld %lld\n",sum[stack[]],ansb[stack[]],ansa[stack[]]);
for(long long i=;i<=e;++i) vis[q[i]]=;
vir.dele(stack[],stack[]);
}
return ;
}
【Luogu】P4103大工程(虚树DP)的更多相关文章
- [HEOI2014][bzoj3611] 大工程 [虚树+dp]
题面: 传送门 思路: 又是一道虚树入门级的题目,但是这道题的实际难点在于dp 首先,这道题是可以点分治做的,而且因为6s时限随便浪,所以写点分治也不是不可以 但是,dp因为$O\left(n\rig ...
- bzoj 3611[Heoi2014]大工程 虚树+dp
题意: 给一棵树 每次选 k 个关键点,然后在它们两两之间 新建 C(k,2)条 新通道. 求: 1.这些新通道的代价和 2.这些新通道中代价最小的是多少 3.这些新通道中代价最大的是多少 分析:较常 ...
- luogu P4103 [HEOI2014]大工程 虚树 + 树形 DP
Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通 ...
- 洛谷P4103 [HEOI2014]大工程(虚树 树形dp)
题意 链接 Sol 虚树. 首先建出虚树,然后直接树形dp就行了. 最大最小值直接维护子树内到该节点的最大值,然后合并两棵子树的时候更新一下答案. 任意两点的路径和可以考虑每条边两边的贡献,\(d[x ...
- BZOJ.3611.[HEOI2014]大工程(虚树 树形DP)
题目链接 要求的和.最大值.最小值好像都可以通过O(n)的树形DP做,总询问点数<=2n. 于是建虚树就可以了.具体DP见DP()函数,维护三个值sum[],mx[],mn[]. sum[]要开 ...
- bzoj 3611(洛谷 4103) [Heoi2014]大工程——虚树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3611 https://www.luogu.org/problemnew/show/P4103 ...
- bzoj 3611: [Heoi2014]大工程 虚树
题目: 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 ...
- 【HEOI2014】大工程<虚树>
虚树 我们每天都用心思索着,这究竟是为了什么呢?我想我也不知道,只是觉得如果人不思考问题就很无聊. 我觉得虚树不是什么数据结构,就是一种技巧或者工具.它能把树中\(k\)个关键点以\(O(klogk) ...
- BZOJ 3611 [Heoi2014]大工程 ——虚树
虚树第二题.... 同BZOJ2286 #include <map> #include <cmath> #include <queue> #include < ...
- bzoj 3572世界树 虚树+dp
题目大意: 给一棵树,每次给出一些关键点,对于树上每个点,被离它最近的关键点(距离相同被标号最小的)控制 求每个关键点控制多少个点 分析: 虚树+dp dp过程如下: 第一次dp,递归求出每个点子树中 ...
随机推荐
- nvl()函数和nvl2()函数
如果你某个字段为空,但是你想让这个字段显示0,可以使用nvl(字段名,0),当然这个0也可以换成其他东西,如:1,2,3…… 一 NVL(表达式1,表达式2) 如果表达式1为空值,NVL返回值为表达式 ...
- SHGetSpecialFolderLocation获取开始文件夹
SHGetSpecialFolderLocation函数可以获取windows 特殊目录 函数原型:(MSDN官方链接:https://msdn.microsoft.com/en-us/library ...
- MySql错误1045 Access denied for user 'root'@'localhost' (using password:YES)
1.先停止mysql服务 2.进入mysql的安装路径,找到并打开my.ini文件,找到[mysqld],在该行下面添加 skip_grant_tables,也就是通知mysql,在登陆的时候跳过密码 ...
- java高并发之CountDownLatch,CyclicBarrier和join
晚上打车回家,在车上看到一篇文章<22岁大学生获谷歌天价Offer,年薪千万!>,讲的是印度一个22岁大学生多次参加ACM大赛,开源多个项目,以非常牛逼的履历通过了谷歌的AI测试,斩获谷歌 ...
- Allowed memory size of 134217728 bytes exhausted (tried to allocate 2 bytes)
出现 Allowed memory size of 134217728 bytes exhausted (tried to allocate 2 bytes)时在php.ini文件中配置 memor ...
- 华为ensp工具栏丢失解决方法
电脑是win8系统 不知道什么原因,华为模拟器的工具栏神奇的消失了,感觉很郁闷,每次要写字的时候都找不到在哪里(菜单里也没有),于是在官方论坛里面找了一下终于找出原因了. 关闭ensp,点击属性,进入 ...
- P1338 末日的传说 逆序数对
题目描述 只要是参加jsoi活动的同学一定都听说过Hanoi塔的传说:三根柱子上的金片每天被移动一次,当所有的金片都被移完之后,世界末日也就随之降临了. 在古老东方的幻想乡,人们都采用一种奇特的方式记 ...
- CentOS网络设置 couldn't resolve host 'mirrorlist.centos.org问题解决
在VMWare上安装好centos后,使用yum安装nodejs报错:can not resolve host 'mirritlist.centos.org', 百度上很多都说在/etc/resolv ...
- PHP.34-TP框架商城应用实例-后台10-商品分类-需求分析、创建无限级商品分类,递归
商品管理需求分析 1.实现商品无限级分类管理[类似京东三级分类] 2.添加商品时要指定商品属于一个主分类和多个扩展分类[扩展分类可以是其他主分类] 3.商品列表中可以根据分类搜索商品 a) 搜索一个分 ...
- ClassNotFountException 与 NoClassDefineError
一 知识准备 NoClassDefFoundError:正如它们的名字所说明的是一个错误 (Error),而ClassNotFoundException是一个异常.正如上一章节所说Exception和 ...