构建出虚树然后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. godaddy 亚太机房 更换 美国机房 全过程(图)

    其它我就不说了,直接干货... 如果要换机房的话,要先支付134元人民币.在哪里支付,怎么支付我就不说了,自己在后台找... 关键的地方来了:当你支付完134元,你回到步骤3会发现没有美国机房选择,呵 ...

  2. Godaddy新手教程

    Godaddy新版域名空间管理控制面板使用方法和更换IP与机房问题 http://www.freehao123.com/godaddy-new/ //设置DNS 最新Godaddy绑定域名教程设置DN ...

  3. Revit Family API 添加材质参数设置可见性

    start //添加类型 void AddType(FamilyManager familyMgr, string name, double w, double d) {     FamilyType ...

  4. 基于ASP.NET WebAPI OWIN实现Self-Host项目实战

    引用 寄宿ASP.NET Web API 不一定需要IIS 的支持,我们可以采用Self Host 的方式使用任意类型的应用程序(控制台.Windows Forms 应用.WPF 应用甚至是Windo ...

  5. 在Visual Studio中使用组件图描述项目组件依赖关系

    如果想描述项目组件的关系,可以考虑使用UML组建图. 在建模项目下添加一个名称为"Applicaiton Component Structure"的UML组建图. 添加各个组件,并 ...

  6. Delphi XE中String、ANSIString、TBytes之间的转换

    一.string转为ansistring1.直接赋值 (有警告)2.ansistring()类型强制转换.(无警告) 二.ansistring 转为string 1.直接赋值 (有警告)2.strin ...

  7. 线程、线程ID获取

    一.进程ID获取 1.1  当前进程的Id 方法1 通过进程名获取 下面的例子中,也包含了获取该进程下的线程的方法. System.Diagnostics.Process[] processes:bo ...

  8. I/O会一直占用CPU吗?【转载】

    转自:https://www.zhihu.com/question/27734728 知乎上看到的一个提问,可以参考 如下图:(图片摘自网络) 在进行I/O操作的时候,是将任务交给DMA来处理,请求发 ...

  9. zTree树

    <link rel="stylesheet" href="/static/zTreeV3/css/metroStyle/metroStyle.css" t ...

  10. 【Devops】【docker】【CI/CD】2.docker启动jenkins环境+安装必要的插件

    [注意:]jenkins的docker镜像,需要从官网进入直接获取,其他地方获取到的docker镜像,可能因为Jenkins版本过低,导致后续插件安装失败等问题!!! ================ ...