【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,递归求出每个点子树中 ...
随机推荐
- 【Java】多线程相关复习—— 线程的创建、名字、运行情况以及顺序控制(join方法) 【一】
一.创建线程的三种方式 · 继承Thread类 · 实现Runnable接口 · 实现Callable接口 二. 线程状态 · 线程名字 getName() · 线程活动情况 isAlive() · ...
- 第一次发干货Observable.zip与Observable.forkJoin
在IT界已经混了5年了,5年中浏览了不少的网站,在上面查询自己想要的东西,解决工作中遇到的问题,心里总想有天自己能够有自己的博客,能给分享一些自己在生活中.工作中遇到的问题,让其他有类似经历的朋友能够 ...
- C#后台动态添加Grid表格
前面页面: <ScrollViewer x:Name=" BorderBrush="#25A0DA" VerticalScrollBarVisibility=&qu ...
- 安装阿里云版Linux云服务器,配置软件
1. 购买域名 2. 购买云服务器ecs 3. 远程访问云服务器并装上Java环境和必备软件 3.1安装远程访问工具 3.2 jdk环境配置 3.3 Mysql依赖关系 重新配置MySQL的远程 ...
- Codeforces146D 概率DP
Bag of mice The dragon and the princess are arguing about what to do on the New Year's Eve. The drag ...
- 单源次短路径:poj:3255-Roadblocks
Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 17521 Accepted: 6167 Descripti ...
- PHP.32-TP框架商城应用实例-后台8-商品相册-添加
商品相册[是商品的其他相片] 添加相册需求: 每张图片生成三张缩略图{50*50.350*350.650*650} 1.建表p39_goods_pic{id,pic,sm_pic,mid_pic,bi ...
- [bzoj3196][tyvj1728]普通平衡树
真是太差了,到现在才打出一个平衡树的板子.. 感谢blackjack大佬提供的数组版treap板子!!基本完全照搬,blackjack太神啦! 但目前我只会这几个最基本的操作(说白了STL的(mult ...
- 8 定制10MINs 3
1. <div class="ui inverted red basic segment"> <h3 class="ui header"> ...
- CentOS 7 安装Oracle 11gR2
概述 Oracle 在Linux和window上的安装不太一样,公司又是Linux系统上的Oracle,实在没辙,研究下Linux下Oracle的使用,oracle默认不支持CentOS系统安装,所以 ...