构建出虚树然后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. delphi 消息的使用

    //分析结果 WM_AnalysisResult = WM_USER + 1009; SendMessage(G_MainHandle, WM_AnalysisResult, 0, 0); proce ...

  2. 怎样用javascript获取UUID

    因为javascript是单线程的东西,所以我们放一个累加变量作为id也不会反复. 但事实上javascript本身提供了能够获得唯一id的东东.还记得setTimeout()方法会返回一个唯一id用 ...

  3. EF Code First更新数据库时报错:provider: SQL Network Interfaces, error: 26

    在使用EF Code First更新数据库时报如下错误: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Serv ...

  4. ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积01, 在控制台实现

    在电商产品模块中必经的一个环节是:当选择某一个产品类别,动态生成该类别下的所有属性和属性项,这些属性项有些是以DropDownList的形式存在,有些是以CheckBoxList的形式存在.接着,把C ...

  5. 使用 MVVMLight 绑定数据(转)

    MVVMLight绑定数据示例 好了,我们在新建了两个项目,分别是“MVVMLight的主程序” 与  “Model层”,运行的效果及解决方案结构如下: 其实很简单,就是绑定了一个数据源而已,编写的代 ...

  6. ListBox使用

    一.什么是ListBox? ListBox 是一个显示项集合的控件.一次可以显示 ListBox 中的多个项. ListBox继承自ItemsControl,可以使用Items或者ItemsSourc ...

  7. Xcode 统计项目代码行数及常用快捷键

    1.统计Xcode项目代码行数 1   打开终端. 2  用ls和cd进到你项目的路径. 3   输入下面的指令: grep -r "\n" classes | wc -l (cl ...

  8. android Installation error: INSTALL_FAILED_VERSION_DOWNGRADE

    http://www.apkbus.com/android-114019-1-1.html   提高 AndroidManifest.xml中的manifest的android:versionCode ...

  9. Pandas 快速入门(二)

    本文的例子需要一些特殊设置,具体可以参考 Pandas快速入门(一) 数据清理和转换 我们在进行数据处理时,拿到的数据可能不符合我们的要求.有很多种情况,包括部分数据缺失,一些数据的格式不正确,一些数 ...

  10. Java Collection Framework : List

    摘要: List 是 Java Collection Framework的重要成员,详细包括List接口及其全部的实现类.由于List接口继承了Collection接口,所以List拥有Collect ...