构建出虚树然后DP统计答案

自己写的DP太傻QAQ,各种WA

膜了一发PoPoQQQ大爷的DP方法

mxdis,mndis分别表示到当前点近期和最远的被选出来的点的距离

mx,mn分别表示在以当前点为根的情况下距离最远的两点的距离和距离近期的两点的距离。

sum表示在以当前点为根的子树中,全部关键的到当前点的距离之和

c数组表示以当前点为根的子树中。关键点的个数

然后我用了个时间戳来标记关键点

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define inf 0x7FFFFFFF
#define ll long long
#define N 1000005
using namespace std;
int sc()
{
int i=0,f=1; char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
return i*f;
}
ll mx[N],mn[N],mn_dis[N],mx_dis[N],c[N],sum[N],ans;
int Head[N],Nxt[N],Lst[N];
int a[N],st[N],tim[N];
int size[N],deep[N],fa[N],S[N],top[N];
int head[N],lst[N<<1],nxt[N<<1],v[N<<1];
int n,tot,cnt,Tot,TI;
void Insert(int x,int y)
{
Lst[++Tot]=y;Nxt[Tot]=Head[x];Head[x]=Tot;
}
void insert(int x,int y)
{
lst[++tot]=y;nxt[tot]=head[x];head[x]=tot;
lst[++tot]=x;nxt[tot]=head[y];head[y]=tot;
}
void dfs(int x,int f)
{
size[x]=1;
for(int i=head[x];i;i=nxt[i])
if(lst[i]!=f)
{
deep[lst[i]]=deep[x]+1;
fa[lst[i]]=x;
dfs(lst[i],x);
size[x]+=size[lst[i]];
}
}
void _dfs(int x,int htp)
{
int k=0;top[x]=htp;S[x]=++cnt;
for(int i=head[x];i;i=nxt[i])
if(lst[i]!=fa[x]&&size[lst[i]]>size[k])k=lst[i];
if(!k)return;_dfs(k,htp);
for(int i=head[x];i;i=nxt[i])
if(lst[i]!=k&&lst[i]!=fa[x])
_dfs(lst[i],lst[i]);
}
int Lca(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
x=fa[top[x]];
}
return deep[x]<deep[y]? x:y;
}
bool cmp(int x,int y){return S[x]<S[y];}
ll dis(int x,int y)
{
return deep[x]+deep[y]-2*deep[Lca(x,y)];
}
void dp(int x)
{
c[x]=tim[x]==TI;sum[x]=0;
mx_dis[x]=tim[x]==TI?0:-inf;
mn_dis[x]=tim[x]==TI?0:inf;
mn[x]=inf;mx[x]=-inf;
for(int i=Head[x];i;i=Nxt[i])
{
ll d=dis(Lst[i],x); dp(Lst[i]);
ans+=sum[x]*c[Lst[i]]+(sum[Lst[i]]+c[Lst[i]]*d)*c[x];
c[x]+=c[Lst[i]];
sum[x]+=sum[Lst[i]]+c[Lst[i]]*d;
mx[x]=max(mx[x],max(mx[Lst[i]],mx_dis[Lst[i]]+d+mx_dis[x]));
mn[x]=min(mn[x],min(mn[Lst[i]],mn_dis[Lst[i]]+d+mn_dis[x]));
mx_dis[x]=max(mx_dis[x],mx_dis[Lst[i]]+d);
mn_dis[x]=min(mn_dis[x],mn_dis[Lst[i]]+d);
}
Head[x]=0;
} void solve()
{
int n=sc(),top=0;Tot=0;TI++;
for(int i=1;i<=n;i++)
tim[a[i]=sc()]=TI;
sort(a+1,a+n+1,cmp);
if(a[1]!=1)st[++top]=1;
for(int i=1;i<=n;i++)
{
int t=a[i],f=0;
while(top)
{
f=Lca(st[top],t);
if(top>1&&deep[f]<deep[st[top-1]]) Insert(st[top-1],st[top]),top--;
else if(deep[f]<deep[st[top]]){Insert(f,st[top]);top--;break;}
else break;
}
if(st[top]!=f&&f)st[++top]=f;
st[++top]=t;
}
while(--top)Insert(st[top],st[top+1]);
ans=0;dp(1);
printf("%lld %lld %lld\n",ans,mn[1],mx[1]);
}
int main()
{
n=sc();
for(int i=1;i<n;i++)
{
int x=sc(),y=sc();
insert(x,y);
}
dfs(1,0);_dfs(1,1);
for(int i=1,m=sc();i<=m;i++)
solve();
return 0;
}

3611: [Heoi2014]大project|树形DP|虚树的更多相关文章

  1. BZOJ3611:[HEOI2014]大工程(树形DP,虚树)

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

  2. [BZOJ3611] [Heoi2014]大工程(DP + 虚树)

    传送门 $dp[i][0]$表示节点i到子树中的所有点的距离之和 $dp[i][1]$表示节点i到子树中最近距离的点的距离 $dp[i][2]$表示节点i到子树中最远距离的点的距离 建好虚树后dp即可 ...

  3. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  4. 【CF809E】Surprise me! 树形DP 虚树 数学

    题目大意 给你一棵\(n\)个点的树,每个点有权值\(a_i\),\(a\)为一个排列,求 \[ \frac{1}{n(n-1)}\sum_{i=1}^n\sum_{j=1}^n \varphi(a_ ...

  5. CF613D:Kingdom and its Cities(树形DP,虚树)

    Description 一个王国有n座城市,城市之间由n-1条道路相连,形成一个树结构,国王决定将一些城市设为重要城市. 这个国家有的时候会遭受外敌入侵,重要城市由于加强了防护,一定不会被占领.而非重 ...

  6. BZOJ2286:[SDOI2011]消耗战(树形DP,虚树)

    Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军 ...

  7. 3611: [Heoi2014]大工程

    3611: [Heoi2014]大工程 链接 分析: 树形dp+虚树. 首先建立虚树,在虚树上dp. dp:sum[i]为i的子树中所有询问点之间的和.siz[i]为i的子树中有多少询问点,mn[i] ...

  8. bzoj 3611 [Heoi2014]大工程(虚树+DP)

    3611: [Heoi2014]大工程 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 408  Solved: 190[Submit][Status] ...

  9. HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...

随机推荐

  1. [Winform]js与webbrowser交互

    摘要 目前项目中采用的方式是内嵌浏览器的方式,打开本地或者互联网上的h5页面.在开发之前做了一下调研.目前常用的在C#封装的浏览器内核中,Chromium 内核封装有Xilium.Cefglue.Ce ...

  2. Python可视化库

    转自小小蒲公英原文用Python可视化库 现如今大数据已人尽皆知,但在这个信息大爆炸的时代里,空有海量数据是无实际使用价值,更不要说帮助管理者进行业务决策.那么数据有什么价值呢?用什么样的手段才能把数 ...

  3. future封装了callable,thread封装future。

    三.使用Callable,Future返回结果 总结:future封装了callable,thread封装future.将callable的返回结果封装在future中,thread封装future, ...

  4. python测试开发django-16.JsonResponse返回中文编码问题

    前言 django查询到的结果,用JsonResponse返回在页面上显示类似于\u4e2d\u6587 ,注意这个不叫乱码,这个是unicode编码,python3默认返回的编码 遇到问题 接着前面 ...

  5. System.loadLibrary()的使用方法汇总

    当使用System.loadLibrary()调用 Dll,两种方法: 1.设定环境变量. 比如:所编辑的Dll在目录“D:/cppProjects/nativecode/release”内,将这个路 ...

  6. 超能英雄第一至四季/全集Heroes迅雷下载

    本季第一.二.三.四季 Heroes Season (2006-2009) 看点:<Heroes>是NBC电视台于2006年九月开播的最新科幻电视剧.Heroes(中文剧名为“英雄”或“天 ...

  7. mariadb 重置密码

    1. sudo身份打开 /etc/mysql/my.cnf 在[mysqld]节点下增加如下代码: skip-grant-tables #忽略密码授权 2. 杀掉mysql进程,重启mariadb,这 ...

  8. Java并发编程的艺术(十一)——线程池(2)

    Executor两级调度模型 在HotSpot虚拟机中,Java中的线程将会被一一映射为操作系统的线程. 在Java虚拟机层面,用户将多个任务提交给Executor框架,Executor负责分配线程执 ...

  9. [Web 前端] React高级教程(es6)——(2)对于Refs最新变动的理解

    cp : https://blog.csdn.net/liwusen/article/details/53384561 1.什么是ReactJS中的refs 在React中组件并不是真实的 DOM 节 ...

  10. IE8 MIME type application/json not found

    如果: public ContentResult GetPaper(string testId) {     return ControllProctector.Do1(() =>        ...