bzoj 3572 [Hnoi2014]世界树——虚树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3572
关于虚树:https://www.cnblogs.com/zzqsblog/p/5560645.html
构造方法:
先把关键点按 dfs 序排序,然后依次插入树中;
插入当前点 cr 的时候,求 lca = get_lca( cr , sta[top] ) ;如果 dep[ sta[top] ] >= dep[lca] ,就一直弹栈;
弹栈结束后,看看现在的 sta[ top ] 是不是就是 lca 了,如果不是,就 sta[ ++ top ] = lca ;同时 fa[ sta[top+1] ] = lca , fa[ lca ] = sta[ top ] ;
把 cr 也加入栈中,即 sta[++top] = cr , fa[ cr ] = lca 。
sta[ 1 ] 就是虚树的根。
关于这道题:http://hzwer.com/6804.html
建好虚树,先换根 dp 得出虚树上的每个点应该被哪个点控制。换根的时候不用去掉该子树的贡献,因为不会有影响。
然后枚举虚树上的每条边 ( cr , fa ),用倍增在边上找到最浅的应该 “被控制 cr 的点控制” 的点 v ,然后 siz[v] - siz[cr] 和 siz[tv] - siz[v] 分别贡献即可,其中 tv 是 fa 在 v 方向的直接孩子。
关于不是虚树的点也不在虚树边上的那些点,自己的方法是在换根 dp 的时候处理;那个时候枚举孩子 v 的时候通过找 tv ,可以知道每个虚树上的点 cr 的不在虚树上的孩子们的 siz 和,直接贡献给控制 cr 的那个点即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mkp make_pair
#define fir first
#define sec second
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=3e5+,K=;
int n,hd[N],xnt,to[N<<],nxt[N<<];
int dfn[N],dep[N],pre[N][K+],bin[K+],lg[N],siz[N],sm[N];
pair<int,int> dp[N];
int m,ans[N],tt,sta[N],tot,fa[N],h2[N],xt2,t2[N<<],nt2[N<<];
struct Node{int v,id;}q[N]; bool cmp(Node x,Node y){return dfn[x.v]<dfn[y.v];}
void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
void ad2(int x,int y){t2[++xt2]=y;nt2[xt2]=h2[x];h2[x]=xt2;}
void ini_dfs(int cr,int fa)
{
dfn[cr]=++tot; dep[cr]=dep[fa]+;
pre[cr][]=fa; siz[cr]=;
for(int t=,u;(u=pre[pre[cr][t-]][t-]);t++)
pre[cr][t]=u;
for(int i=hd[cr],v;i;i=nxt[i])
if((v=to[i])!=fa)
{
ini_dfs(v,cr); siz[cr]+=siz[v];
}
}
int get_lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int t=lg[dep[x]-dep[y]];t>=;t--)
if(dep[pre[x][t]]>=dep[y])
x=pre[x][t];
if(x==y)return x;
for(int t=lg[dep[x]];t>=;t--)
if(pre[x][t]!=pre[y][t])
x=pre[x][t],y=pre[y][t];
return pre[x][];
}
void build()
{
sort(q+,q+m+,cmp); tt=m; tot=;
for(int i=;i<=m;i++)
{
int cr=q[i].v;
if(!tot){sta[++tot]=cr;dp[cr]=mkp(,cr);continue;}
int lca=get_lca(cr,sta[tot]);
while(dep[sta[tot]]>dep[lca])tot--;
if(sta[tot]!=lca)
{
q[++tt].v=lca; fa[sta[tot+]]=lca;
fa[lca]=sta[tot]; sta[++tot]=lca;
dp[lca]=mkp(N,);
}
fa[cr]=lca; sta[++tot]=cr; dp[cr]=mkp(,cr);
}
for(int i=;i<=tt;i++)if(fa[q[i].v])ad2(fa[q[i].v],q[i].v);
}
void dfs(int cr,int fa)
{
for(int i=h2[cr],v;i;i=nt2[i])
if((v=t2[i])!=fa)
{
dfs(v,cr);
int tp1=dp[v].fir+dep[v]-dep[cr],tp2=dp[cr].fir;
if(tp1<tp2||(tp1==tp2&&dp[v].sec<dp[cr].sec))
dp[cr].fir=tp1,dp[cr].sec=dp[v].sec;
}
}
int fnd2(int cr,int fa)
{
int d=dep[cr]-dep[fa]-;
while(d)
{
int lbt=(d&-d);
cr=pre[cr][lg[lbt]]; d-=lbt;
}
return cr;
}
void dfsx(int cr,int fa)
{
int tp1=dp[fa].fir+dep[cr]-dep[fa],tp2=dp[cr].fir;
if(fa&&(tp1<tp2||(tp1==tp2&&dp[fa].sec<dp[cr].sec)))
dp[cr].fir=tp1,dp[cr].sec=dp[fa].sec;
int s=siz[cr];
for(int i=h2[cr],v;i;i=nt2[i])
if((v=t2[i])!=fa)
{
int tv=fnd2(v,cr);
s-=siz[tv]; dfsx(v,cr);
}
sm[dp[cr].sec]+=s-;//-1 for zj
}
int fnd(int cr,int fa)
{
bool fg=(dp[cr].sec<dp[fa].sec);
int x=dp[cr].fir,y=dp[fa].fir,d1=dep[cr],d2=dep[fa];
for(int t=lg[dep[cr]-dep[fa]];t>=;t--)
{
int d=dep[pre[cr][t]];
int u=d1-d+x,v=d-d2+y;
if(u<v||(u==v&&fg))cr=pre[cr][t];
}
return cr;
}
bool In(int cr,int fa){return dfn[cr]>=dfn[fa]&&dfn[cr]<dfn[fa]+siz[fa];}
void solve()
{
for(int i=;i<=m;i++)sm[q[i].v]=;
int rt=sta[]; dfs(rt,); dfsx(rt,);
for(int i=;i<=tt;i++)sm[dp[q[i].v].sec]++;
for(int i=;i<=tt;i++)
{
int cr=q[i].v,f=fa[cr];
if(!f) {sm[dp[cr].sec]+=n-siz[cr];continue;}
int v=fnd(cr,f),tv=fnd2(cr,f);
sm[dp[cr].sec]+=siz[v==f?tv:v]-siz[cr];//
sm[dp[f].sec]+=siz[tv]-siz[v==f?tv:v];//tv//
}
for(int i=;i<=m;i++)ans[q[i].id]=sm[q[i].v];
for(int i=;i<=m;i++)printf("%d ",ans[i]); puts("");
}
int main()
{
n=rdn();
for(int i=,u,v;i<n;i++)
u=rdn(),v=rdn(),add(u,v),add(v,u);
bin[]=;for(int i=;i<=K;i++)bin[i]=bin[i-]<<;
for(int i=;i<=n;i++)lg[i]=lg[i>>]+;
ini_dfs(,); int Q=rdn();
while(Q--)
{
for(int i=;i<=tt;i++)h2[q[i].v]=; xt2=;
for(int i=;i<=tt;i++)fa[q[i].v]=;///
m=rdn(); for(int i=;i<=m;i++)q[i].v=rdn(),q[i].id=i;
build(); solve();
}
return ;
}
bzoj 3572 [Hnoi2014]世界树——虚树的更多相关文章
- bzoj 3572: [Hnoi2014]世界树 虚树 && AC500
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 520 Solved: 300[Submit][Status] ...
- BZOJ 3572: [Hnoi2014]世界树 虚树 树形dp
https://www.lydsy.com/JudgeOnline/problem.php?id=3572 http://hzwer.com/6804.html 写的时候参考了hzwer的代码,不会写 ...
- bzoj 3572: [Hnoi2014]世界树 虚树
题目: Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生 ...
- BZOJ 3572 [HNOI2014]世界树 (虚树+DP)
题面:BZOJ传送门 洛谷传送门 题目大意:略 细节贼多的虚树$DP$ 先考虑只有一次询问的情况 一个节点$x$可能被它子树内的一个到x距离最小的特殊点管辖,还可能被管辖fa[x]的特殊点管辖 跑两次 ...
- BZOJ 3572: [Hnoi2014]世界树 [虚树 DP 倍增]
传送门 题意: 一棵树,多次询问,给出$m$个点,求有几个点到给定点最近 写了一晚上... 当然要建虚树了,但是怎么$DP$啊 大爷题解传送门 我们先求出到虚树上某个点最近的关键点 然后枚举所有的边$ ...
- 【BZOJ】3572: [Hnoi2014]世界树 虚树+倍增
[题意]给定n个点的树,m次询问,每次给定ki个特殊点,一个点会被最近的特殊点控制,询问每个特殊点控制多少点.n,m,Σki<=300000. [算法]虚树+倍增 [题解]★参考:thy_asd ...
- BZOJ 3572: [Hnoi2014]世界树
BZOJ 3572: [Hnoi2014]世界树 标签(空格分隔): OI-BZOJ OI-虚数 OI-树形dp OI-倍增 Time Limit: 20 Sec Memory Limit: 512 ...
- bzoj 3572 [Hnoi2014]世界树(虚树+DP)
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 645 Solved: 362[Submit][Status] ...
- 【BZOJ3572】[Hnoi2014]世界树 虚树
[BZOJ3572][Hnoi2014]世界树 Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森 ...
随机推荐
- HTML5绘制几何图形
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> < ...
- 获取和设置消息队列的属性msgctl,删除消息队列
消息队列的属性保存在系统维护的数据结构msqid_ds中,用户可以通过函数msgctl获取或设置消息队列的属性. int msgctl(int msqid, int cmd, struct msqid ...
- memory prefix twi,tri,trans ,tetra out 4
1● twi 二 2● tri 三 3● trans 超过,超载 4● tetra 立体
- sqlite 查询数据库中所有的表名,判断某表是否存在,将某列所有数值去重后获得数量
1.列出当前db文件中所有的表的表名 SQL语句:SELECT * FROM sqlite_master WHERE type='table'; 结构如下: 注:网上有人说可以带上db文件的名称,如: ...
- httpclient httpclient连接回收
httpclient连接释放 httpClient必须releaseConnection,但不是abort.因为releaseconnection是归还连接到到连接池,而abort是直接抛弃这个连接, ...
- [.NET MVC4 入门系列01]Helloworld MVC 4 第一个MVC4程序
[.NET MVC4 入门系列01]Helloworld MVC 4 第一个MVC4程序 一.练习项目: http://www.asp.net/mvc/tutorials/mvc-4/gettin ...
- bzoj1083
题解: 简单最小生成树 代码: #include<bits/stdc++.h> using namespace std; #define y1 ____y1 ; int z[N],f[N] ...
- 参数 out
function outtest(out jo: ISuperObject; out s: string):Boolean; begin //进入函数时 jo =nil ErrStr = '' Res ...
- Swift语法笔记
Guard guard是一种条件判断语句,可以类比if.assert.如果条件不符合,guard的else语句就运行,从而退出这个函数. 具体写法如下: func fooGuard(x: Int?) ...
- WLAN 802.11 a/b/g PHY Specification and EDVT Measurement III
Transmit Rated Emission (FCC) AC power conducted emission.-FCC 15.207 Minimum 6 dB bandwidth. -500kH ...