题目链接

  我貌似发现这类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)的更多相关文章

  1. [HEOI2014][bzoj3611] 大工程 [虚树+dp]

    题面: 传送门 思路: 又是一道虚树入门级的题目,但是这道题的实际难点在于dp 首先,这道题是可以点分治做的,而且因为6s时限随便浪,所以写点分治也不是不可以 但是,dp因为$O\left(n\rig ...

  2. bzoj 3611[Heoi2014]大工程 虚树+dp

    题意: 给一棵树 每次选 k 个关键点,然后在它们两两之间 新建 C(k,2)条 新通道. 求: 1.这些新通道的代价和 2.这些新通道中代价最小的是多少 3.这些新通道中代价最大的是多少 分析:较常 ...

  3. luogu P4103 [HEOI2014]大工程 虚树 + 树形 DP

    Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道.  我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上.  在 2 个国家 a,b 之间建一条新通 ...

  4. 洛谷P4103 [HEOI2014]大工程(虚树 树形dp)

    题意 链接 Sol 虚树. 首先建出虚树,然后直接树形dp就行了. 最大最小值直接维护子树内到该节点的最大值,然后合并两棵子树的时候更新一下答案. 任意两点的路径和可以考虑每条边两边的贡献,\(d[x ...

  5. BZOJ.3611.[HEOI2014]大工程(虚树 树形DP)

    题目链接 要求的和.最大值.最小值好像都可以通过O(n)的树形DP做,总询问点数<=2n. 于是建虚树就可以了.具体DP见DP()函数,维护三个值sum[],mx[],mn[]. sum[]要开 ...

  6. bzoj 3611(洛谷 4103) [Heoi2014]大工程——虚树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3611 https://www.luogu.org/problemnew/show/P4103 ...

  7. bzoj 3611: [Heoi2014]大工程 虚树

    题目: 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 ...

  8. 【HEOI2014】大工程<虚树>

    虚树 我们每天都用心思索着,这究竟是为了什么呢?我想我也不知道,只是觉得如果人不思考问题就很无聊. 我觉得虚树不是什么数据结构,就是一种技巧或者工具.它能把树中\(k\)个关键点以\(O(klogk) ...

  9. BZOJ 3611 [Heoi2014]大工程 ——虚树

    虚树第二题.... 同BZOJ2286 #include <map> #include <cmath> #include <queue> #include < ...

  10. bzoj 3572世界树 虚树+dp

    题目大意: 给一棵树,每次给出一些关键点,对于树上每个点,被离它最近的关键点(距离相同被标号最小的)控制 求每个关键点控制多少个点 分析: 虚树+dp dp过程如下: 第一次dp,递归求出每个点子树中 ...

随机推荐

  1. 【Java】多线程相关复习—— 线程的创建、名字、运行情况以及顺序控制(join方法) 【一】

    一.创建线程的三种方式 · 继承Thread类 · 实现Runnable接口 · 实现Callable接口 二. 线程状态 · 线程名字 getName() · 线程活动情况 isAlive() · ...

  2. 第一次发干货Observable.zip与Observable.forkJoin

    在IT界已经混了5年了,5年中浏览了不少的网站,在上面查询自己想要的东西,解决工作中遇到的问题,心里总想有天自己能够有自己的博客,能给分享一些自己在生活中.工作中遇到的问题,让其他有类似经历的朋友能够 ...

  3. C#后台动态添加Grid表格

    前面页面: <ScrollViewer x:Name=" BorderBrush="#25A0DA" VerticalScrollBarVisibility=&qu ...

  4. 安装阿里云版Linux云服务器,配置软件

    1.  购买域名 2.  购买云服务器ecs 3.  远程访问云服务器并装上Java环境和必备软件 3.1安装远程访问工具 3.2 jdk环境配置 3.3 Mysql依赖关系 重新配置MySQL的远程 ...

  5. Codeforces146D 概率DP

    Bag of mice The dragon and the princess are arguing about what to do on the New Year's Eve. The drag ...

  6. 单源次短路径:poj:3255-Roadblocks

    Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 17521 Accepted: 6167 Descripti ...

  7. PHP.32-TP框架商城应用实例-后台8-商品相册-添加

    商品相册[是商品的其他相片] 添加相册需求: 每张图片生成三张缩略图{50*50.350*350.650*650} 1.建表p39_goods_pic{id,pic,sm_pic,mid_pic,bi ...

  8. [bzoj3196][tyvj1728]普通平衡树

    真是太差了,到现在才打出一个平衡树的板子.. 感谢blackjack大佬提供的数组版treap板子!!基本完全照搬,blackjack太神啦! 但目前我只会这几个最基本的操作(说白了STL的(mult ...

  9. 8 定制10MINs 3

    1. <div class="ui inverted red basic segment"> <h3 class="ui header"> ...

  10. CentOS 7 安装Oracle 11gR2

    概述 Oracle 在Linux和window上的安装不太一样,公司又是Linux系统上的Oracle,实在没辙,研究下Linux下Oracle的使用,oracle默认不支持CentOS系统安装,所以 ...