【HEOI2014】大工程<虚树>
虚树
我们每天都用心思索着,这究竟是为了什么呢?我想我也不知道,只是觉得如果人不思考问题就很无聊。
- 我觉得虚树不是什么数据结构,就是一种技巧或者工具。它能把树中\(k\)个关键点以\(O(klogk)\)的复杂度变成一棵节点数\(2*k\)以内的树。并且构树的边的信息适用广泛(如最大值,和……)
有两种构树方法:(我这里只讲第一种,第二种男鞋后面看心情)
我们把所有节点按dfn排序,然后相邻两个求的lca加入点中再排序。
用到stack,每个点在加入之前,一直弹栈,直到找到第一个是它祖先的点当做他虚数上的父亲。代码还是挺好写的,就是要求lca.(懒得写st表lca)
然后题目之后就很灵活了,通常是问你一些数论问题。发正她还真是个工具人呢。
大工程
- 题意:【HEOI2014】大工程
- 思路:先构造虚数。然后求解树上最长链、最短链、所有链的和。我就是存Cnt,sum求和(应该大家都是这样),不过最长最短我受了直径的影响有点傻B,存储了最大次大(小),不过也无大碍
- code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int st[N],tp,In[N],Out[N],Time,fa[N][21],nxt[N<<1],to[N<<1],head[N],dep[N],ecnt,lg[N],mark[N];
ll inf=1e18,s1[N],Mn,Sum,Mx,dp[N],mn1[N],mn2[N],mx1[N],mx2[N],sum[N],cnt[N],len[N];
struct node {int p,dfn;}a[N];
bool cmp(node u,node v) {return u.dfn<v.dfn;}
void add_edge(int u,int v,ll w) {nxt[++ecnt]=head[u];to[ecnt]=v;len[ecnt]=w;head[u]=ecnt;}
void init(int u) {
In[u]=++Time;
for(int i=head[u];i;i=nxt[i]) {
int v=to[i];
if(v==fa[u][0])continue;
fa[v][0]=u,dep[v]=dep[u]+1;
for(int j=1;j<=lg[dep[v]];j++) fa[v][j]=fa[fa[v][j-1]][j-1];
init(v);
}
Out[u]=Time;
}
int Lca(int u,int v) {
if(dep[u]<dep[v]) swap(u,v);
int k=dep[u]-dep[v];
for(int i=0;i<=lg[k];i++) if((1<<i)&k)u=fa[u][i];
if(u==v)return u;
for(int i=lg[dep[u]];i>=0;i--)
if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
return fa[u][0];
}
void dfs(int u) {
s1[u]=cnt[u]=mx1[u]=mx2[u]=0;
mn1[u]=mn2[u]=inf;
for(int i=head[u];i;i=nxt[i]) {
int v=to[i];
dfs(v);
cnt[v]+=(mark[v]==1);
ll tmp=s1[v]+cnt[v]*len[i];
// printf("%lld %lld\n",cnt[u],tmp);
Sum+=(cnt[u]+(mark[u]==1))*tmp+cnt[v]*s1[u];
cnt[u]+=cnt[v],s1[u]+=tmp;
tmp=mx1[v]+len[i];
if(mx1[u]<tmp) mx2[u]=mx1[u],mx1[u]=tmp;
else if(mx2[u]<tmp) mx2[u]=tmp;
tmp=mn1[v]+len[i];
if(mn1[u]>tmp) mn2[u]=mn1[u],mn1[u]=tmp;
else if(mn2[u]>tmp) mn2[u]=tmp;
}
if(mark[u]==1) {Mn=min(Mn,mn1[u]);mn1[u]=0;}
else Mn=min(Mn,mn1[u]+mn2[u]);
Mx=max(Mx,mx1[u]+mx2[u]);
}
int main() {
int n,m;
scanf("%d",&n);
lg[1]=0;for(int j=2;j<=n;j++)lg[j]=lg[j>>1]+1;
for(int i=1;i<n;i++) {
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v,0),add_edge(v,u,0);
}
init(1);
ecnt=0;for(int i=1;i<=n;i++)head[i]=0;
scanf("%d",&m);
while(m--) {
int ct=0,cc; scanf("%d",&cc);
for(int i=1;i<=cc;i++) {
int p; scanf("%d",&p);
a[++ct]=(node){p,In[p]}; mark[p]=1;
}
sort(a+1,a+1+ct,cmp);
for(int i=1;i<ct;i++) {
int c=Lca(a[i].p,a[i+1].p);
if(!mark[c])a[++ct]=(node){c,In[c]},mark[c]=2;
}
sort(a+1,a+1+ct,cmp);
tp=0;
st[++tp]=a[1].p;
for(int i=2;i<=ct;i++) {
int u=a[i].p;
while(tp&&In[u]<In[st[tp]]||In[u]>Out[st[tp]]) tp--;
add_edge(st[tp],u,dep[u]-dep[st[tp]]);
// printf("!%d %d %d\n",st[tp],u,dep[u]-dep[st[tp]]);
st[++tp]=u;
}
Mn=1e18,Mx=Sum=0;
dfs(a[1].p);
printf("%lld %lld %lld\n",Sum,Mn,Mx);
for(int i=1;i<=ct;i++) mark[a[i].p]=head[a[i].p]=0; ecnt=0;
}
return 0;
}
【HEOI2014】大工程<虚树>的更多相关文章
- bzoj 3611: [Heoi2014]大工程 虚树
题目: 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 ...
- luogu P4103 [HEOI2014]大工程 虚树 + 树形 DP
Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通 ...
- 洛谷P4103 [HEOI2014]大工程(虚树 树形dp)
题意 链接 Sol 虚树. 首先建出虚树,然后直接树形dp就行了. 最大最小值直接维护子树内到该节点的最大值,然后合并两棵子树的时候更新一下答案. 任意两点的路径和可以考虑每条边两边的贡献,\(d[x ...
- bzoj 3611(洛谷 4103) [Heoi2014]大工程——虚树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3611 https://www.luogu.org/problemnew/show/P4103 ...
- BZOJ.3611.[HEOI2014]大工程(虚树 树形DP)
题目链接 要求的和.最大值.最小值好像都可以通过O(n)的树形DP做,总询问点数<=2n. 于是建虚树就可以了.具体DP见DP()函数,维护三个值sum[],mx[],mn[]. sum[]要开 ...
- BZOJ 3611 [Heoi2014]大工程 ——虚树
虚树第二题.... 同BZOJ2286 #include <map> #include <cmath> #include <queue> #include < ...
- bzoj 3611[Heoi2014]大工程 虚树+dp
题意: 给一棵树 每次选 k 个关键点,然后在它们两两之间 新建 C(k,2)条 新通道. 求: 1.这些新通道的代价和 2.这些新通道中代价最小的是多少 3.这些新通道中代价最大的是多少 分析:较常 ...
- [HEOI2014][bzoj3611] 大工程 [虚树+dp]
题面: 传送门 思路: 又是一道虚树入门级的题目,但是这道题的实际难点在于dp 首先,这道题是可以点分治做的,而且因为6s时限随便浪,所以写点分治也不是不可以 但是,dp因为$O\left(n\rig ...
- bzoj 3611 [Heoi2014]大工程(虚树+DP)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 408 Solved: 190[Submit][Status] ...
随机推荐
- 多条命令同时执行的包concurrently
npm i concurrently use "script":{ "client:build": "webpack --config build/w ...
- 搭建springboot集成mybatis
1.new project创建新项目选择spring initializr: 2.选择依赖需要选择web.mybatis.mysql就够了,后续需要其他的直接pom引入依赖就好了: 3.自己在java ...
- eclipse项目导入工作空间提示已存在问题
项目直接放在 workspace 目录下,必须项目名和项目文件夹名相同,主要找的是eclipse 项目文件夹下的 .project 文件中的 <name> ... </name> ...
- 【直播回顾】OpenHarmony知识赋能第四期第三课——I2C驱动开发
3月24日晚上19点,知识赋能第四期直播的第三节课<OpenHarmony标准系统HDF框架之I2C驱动开发>,在OpenHarmony开发者成长计划社群内成功举办. 本期课程,由拓 ...
- 一款开源的文件搜索神器,终于不用记 find 命令了
这是 HelloGitHub 推出的<讲解开源项目>系列,用一篇文章带你快速上手有趣的开源项目. 今天给大家推荐一个好用+开源的文件搜索工具--fd 该工具支持大多数主流操作系统,快来更新 ...
- js实时监听dom尺寸变化
开发过程中总会遇到dom节点尺寸变化,去做一些相应的逻辑,第一想到的应该是用$(window).resize()去做,但是这个是监听浏览器窗口的所以这个时候要用 ResizeObserver Resi ...
- 通过Nginx TCP反向代理实现Apache Doris负载均衡
概述 Nginx能够实现HTTP.HTTPS协议的负载均衡,也能够实现TCP协议的负载均衡.那么,问题来了,可不可以通过Nginx实现Apache Doris数据库的负载均衡呢?答案是:可以.接下来, ...
- 领域驱动模型DDD(三)——使用Saga管理事务
前言 虽然一直说想写一篇关于Saga模式,在多次尝试后不得不承认这玩意儿的仿制代码真不是我一个菜鸟就能完成的,所以还是妥协般地引用现成的Eventuate Tram Saga框架(虽然我对它一直很反感 ...
- 登录口爆破之ldap的md5加密、验证码认证
ldap的md5加密配合autoDecoder插件.captcha-killer-modified插件 autoDecoder例 需要传入的数据包为: {"username":&q ...
- 通过命令验证docker容器相当一个轻量级的Linux运行环境,且每个容器内都有一个属于自己的文件系统,容器之间相互隔离
一.docker的三个重要概念 1.镜像:打包项目带上环境,即镜像 Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序.库.资源.配置等文件外,还包含了一些为运行时准备的配置参数.镜像 ...