BZOJ 3572 【HNOI2014】 世界树
题目链接:世界树
首先看到\(\sum m_i\le 3\times 10^5\)这个条件,显然这道题就需要用虚树了。
在我们构建出虚树之后,就可以用两遍\(dfs\)来求出离每个点最近的议事处了。然后,如果一个点和它在虚树上的父亲所属的议事处不同,那么在原树中的两点之间的路径上就会存在一个分界点,倍增出这个分界点算答案即可。注意不能用路径长度来算,需要使用子树大小。
然后我们还需要考虑那些不在虚树中的点。我们可以令\(f_x\)表示原树上\(x\)子树中和\(x\)属于同一个议事处的点的个数,那么我们可以把初值赋为\(size_x\),然后减去和它不属于同一个议事处的孩子的\(size\)和这条路径上点的个数即可。然后就可以直接用这个东西和上一部分的贡献一起算出答案了。
想清楚了细节再写的话还是不难写的。
下面贴代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 300010 using namespace std;
typedef long long llg; int head[maxn],next[maxn<<1],to[maxn<<1],tt;
int fa[maxn][19],dep[maxn],n,m,le[maxn],siz[maxn];
int d[maxn],ld,S[maxn],top,qu[maxn],nu[maxn],lq;
int fr[maxn],fd[maxn],ans[maxn],ji[maxn]; int getint(){
int w=0;bool q=0;
char c=getchar();
while((c>'9'||c<'0')&&c!='-') c=getchar();
if(c=='-') c=getchar(),q=1;
while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
return q?-w:w;
} bool cmp(int x,int y){return le[x]<le[y];}
void link(int x,int y){
to[++tt]=y;next[tt]=head[x];head[x]=tt;
to[++tt]=x;next[tt]=head[y];head[y]=tt;
} void dfs(int u,int ff){
fa[u][0]=ff; dep[u]=dep[ff]+1; le[u]=++tt; siz[u]=1;
for(int i=1,now=2;now<dep[u];i++,now<<=1)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u],v;v=to[i],i;i=next[i])
if(v!=ff) dfs(v,u),siz[u]+=siz[v];
} int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y); int t=1;
for(int now=2;now<dep[x];now<<=1) t++;t--;
for(int i=t;i>=0;i--)
if(dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if(x==y) return x;
for(int i=t;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
} bool pd(int a,int b,int c,int d){return (a<b || (a==b && fr[c]<fr[d]));}
int dis(int x,int y){return dep[x]+dep[y]-(dep[lca(x,y)]<<1);}
int jump(int x,int y){
for(int i=18;i>=0;i--)
if(dep[fa[x][i]]>dep[y]) x=fa[x][i];
return x;
} void solve(int x,int y,int l){
int x1=fd[x],x2=fd[y]+dep[x]-dep[y],u=x;
for(int i=18,v,j=1<<18;i>=0;i--,j>>=1){
v=fa[u][i]; if(dep[v]<=dep[y]) continue;
if(pd(x1+j,x2-j,x,y)) x1+=j,x2-=j,u=fa[u][i];
}
ans[nu[fr[x]]]+=siz[u]-siz[x];
ans[nu[fr[y]]]+=siz[l]-siz[u];
} void dfs1(int u,int ff){
for(int i=head[u],v,x;v=to[i],i;i=next[i])
if(v!=ff){
dfs1(v,u);
if(fr[v] && fd[u]){
x=dis(u,fr[v]);
if(pd(x,fd[u],v,u)) fd[u]=x,fr[u]=fr[v];
}
}
} void dfs2(int u,int ff){
int x; ji[u]=siz[u];
if(ff && fr[ff]!=fr[u]){
x=dis(fr[ff],u);
if(pd(x,fd[u],ff,u)) fd[u]=x,fr[u]=fr[ff];
}
for(int i=head[u],v;v=to[i],i;i=next[i])
if(v!=ff){
dfs2(v,u); x=jump(v,u);
if(fr[v]!=fr[u]) ji[u]-=siz[v]+siz[x]-siz[v];
else ans[nu[fr[u]]]-=ji[v],ji[u]-=siz[v]-ji[v];
}
x=jump(u,ff); ans[nu[fr[u]]]+=ji[u];
if(ff && fr[u]!=fr[ff] && ff!=fa[u][0]) solve(u,ff,x);
} int main(){
File("worldtree");
n=getint();
for(int i=2;i<=n;i++) link(getint(),getint());
tt=0; dfs(1,0); tt=0; m=getint();
for(int i=1;i<=n;i++) head[i]=0,fd[i]=n+1;
while(m--){
lq=getint(); tt=0; d[ld=1]=1;
for(int i=1;i<=lq;i++){
nu[qu[i]=getint()]=i;
fr[qu[i]]=qu[i],fd[qu[i]]=0;
}
sort(qu+1,qu+lq+1,cmp); S[top=1]=1;
for(int i=1,L,x;i<=lq;i++){
x=qu[i]; L=lca(x,S[top]);
while(top){
if(top>1 && dep[S[top-1]]>dep[L]) link(S[top-1],S[top]),top--;
else if(dep[S[top]]>dep[L]){link(L,S[top--]);break;}
else break;
}
if(S[top]!=L) S[++top]=L,d[++ld]=L;
if(x!=1) S[++top]=x,d[++ld]=x;
}
while(top>1) link(S[top-1],S[top]),top--;
dfs1(1,0); dfs2(1,0);
for(int i=1,u;u=d[i],i<=ld;i++) head[u]=fr[u]=0,fd[u]=n+1;
for(int i=1;i<=lq;i++) printf("%d ",ans[i]);
for(int i=1;i<=lq;i++) ans[i]=0;
printf("\n");
}
return 0;
}
BZOJ 3572 【HNOI2014】 世界树的更多相关文章
- BZOJ 3572: [Hnoi2014]世界树
BZOJ 3572: [Hnoi2014]世界树 标签(空格分隔): OI-BZOJ OI-虚数 OI-树形dp OI-倍增 Time Limit: 20 Sec Memory Limit: 512 ...
- bzoj 3572: [Hnoi2014]世界树 虚树 && AC500
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 520 Solved: 300[Submit][Status] ...
- bzoj 3572 [Hnoi2014]世界树(虚树+DP)
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 645 Solved: 362[Submit][Status] ...
- bzoj 3572 [Hnoi2014]世界树——虚树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3572 关于虚树:https://www.cnblogs.com/zzqsblog/p/556 ...
- 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]世界树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3572 算是细节题了吧.. 构出虚树,考虑z正反DP两次求出虚树中每个点最近的议事处是哪一个 ...
- 【BZOJ】3572: [Hnoi2014]世界树 虚树+倍增
[题意]给定n个点的树,m次询问,每次给定ki个特殊点,一个点会被最近的特殊点控制,询问每个特殊点控制多少点.n,m,Σki<=300000. [算法]虚树+倍增 [题解]★参考:thy_asd ...
随机推荐
- 【BZOJ1112】[POI2008]砖块Klo Treap
[BZOJ1112][POI2008]砖块Klo Description N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出 ...
- oracle rank()和dense_rank(), row_number() 的区别
转自:http://www.linuxidc.com/Linux/2015-04/116349.htm 假设现在有一张学生表student,学生表中有姓名.分数.课程编号,现在我需要按照课程对学生的成 ...
- 删除Linux的用户
vipw : root@ www.linuxidc.com :/home# vipw 找到你之前创建的用户,用dd删除那行(记得保存:wq or :x)..之后. root@ www.linuxidc ...
- 170621、springboot编程之全局异常捕获
1.创建GlobalExceptionHandler.java,在类上注解@ControllerAdvice,在方法上注解@ExceptionHandler(value = Exception.cla ...
- 2.title
1.母版页里写title,标题会:会显示母版页里的. 结果如下: 2.母版页和实现模板页同时都设置了title,会显示实现模板页里的title 运行结果页:
- https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic net::ERR_CONNECTION_TIMED_OUT问题解决
使用adminTLE时,有时候出现 https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic, ...
- Linux下编译安装PHP扩展redis
[Redis] 先安装tcl: yum install tcl [下载和安装] 官网http://redis.io/ 下载最新的稳定版本,这里是3.2.0, 然后解压文件并进入. $ sudo ta ...
- jQuery-添加、移出事件
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...
- JavaScript的基础语法
对于Javascript的而言没有数据类型的全部都是通过var来定义创建的.比如: <!DOCTYPE html> <html> <head> <meta c ...
- lua关于参数生命周期的研究
local num = 123 local str = "abc" local tb ={} 数字和字符串类型的值作为参数传递的时候,是复制值,2个独立的内存地址 table类型的 ...