[BZO3572][HNOI2014]世界树:虚树+倍增
分析
思维难度几乎为\(0\)的虚树码农(并不)题。
代码
#include <bits/stdc++.h>
#define rin(i,a,b) for(register int i=(a);i<=(b);++i)
#define irin(i,a,b) for(register int i=(a);i>=(b);--i)
#define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
#define itrav(i,a) for(register int i=ihead[a];i;i=ie[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int MAXN=3e5+5;
int n,q,ecnt,head[MAXN];
int tot,id[MAXN],num[MAXN],len,st[MAXN<<1][21],pos[MAXN];
int dep[MAXN],siz[MAXN],anc[MAXN][21];
int m,mm,h[MAXN<<1],hh[MAXN],top,sta[MAXN];
int iecnt,ihead[MAXN];
int ans[MAXN];
bool isc[MAXN];
struct Edge{
int to,nxt;
}e[MAXN<<1];
inline void add_edge(int bg,int ed){
++ecnt;
e[ecnt].to=ed;
e[ecnt].nxt=head[bg];
head[bg]=ecnt;
}
void dfs1(int x,int pre,int depth){
id[x]=++tot;
num[tot]=x;
st[++len][0]=id[x];
pos[x]=len;
dep[x]=depth;
siz[x]=1;
anc[x][0]=pre;
trav(i,x){
int ver=e[i].to;
if(ver==pre) continue;
dfs1(ver,x,depth+1);
st[++len][0]=id[x];
siz[x]+=siz[ver];
}
}
void buildst(){
int lim=log2(len);
rin(i,1,lim) rin(j,1,len-(1<<i)+1)
st[j][i]=std::min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
void buildanc(){
rin(i,1,20) rin(j,1,n)
anc[j][i]=anc[anc[j][i-1]][i-1];
}
inline int lca(int x,int y){
x=pos[x],y=pos[y];
if(x>y) std::swap(x,y);
int lim=log2(y-x+1);
return num[std::min(st[x][lim],st[y-(1<<lim)+1][lim])];
}
inline bool cmp(int x,int y){
return id[x]<id[y];
}
struct iedge{
int to,nxt;
}ie[MAXN];
inline void add_iedge(int bg,int ed){
++iecnt;
ie[iecnt].to=ed;
ie[iecnt].nxt=ihead[bg];
ihead[bg]=iecnt;
}
void build_itree(){
std::sort(h+1,h+m+1,cmp);
rin(i,2,mm) h[++m]=lca(h[i-1],h[i]);
h[++m]=1;
std::sort(h+1,h+m+1,cmp);
m=std::unique(h+1,h+m+1)-h-1;
top=0;
rin(i,1,m){
while(top&&id[h[i]]>id[sta[top]]+siz[sta[top]]-1) add_iedge(sta[top-1],sta[top]),--top;
sta[++top]=h[i];
}
while(top>1) add_iedge(sta[top-1],sta[top]),--top;
--top;
}
struct ctrl{
int pos,dis;
inline friend bool operator < (ctrl A,ctrl B){
return A.dis==B.dis?A.pos<B.pos:A.dis<B.dis;
}
}c[MAXN];
void dfs2(int x){
if(isc[x]) c[x]=(ctrl){x,0};
else c[x]=(ctrl){0,(int)1e9};
itrav(i,x){
int ver=ie[i].to;
dfs2(ver);
c[x]=std::min(c[x],(ctrl){c[ver].pos,c[ver].dis+dep[ver]-dep[x]});
}
}
void dfs3(int x,int pre){
if(pre) c[x]=std::min(c[x],(ctrl){c[pre].pos,c[pre].dis+dep[x]-dep[pre]});
itrav(i,x){
int ver=ie[i].to;
dfs3(ver,x);
}
}
inline int getveranc(int x,int pre){
int ret=x;
irin(i,20,0)
if(dep[anc[ret][i]]>dep[pre])
ret=anc[ret][i];
return ret;
}
inline int climb(int x,int y){
int ret=x,tt=0;
while(y){
if(y&1) ret=anc[ret][tt];
++tt;
y>>=1;
}
return ret;
}
void dfs4(int x,int pre){
ans[c[x].pos]+=siz[x];
itrav(i,x){
int ver=ie[i].to,veranc=getveranc(ver,x);
dfs4(ver,x);
ans[c[x].pos]-=siz[veranc];
if(c[x].pos==c[ver].pos)
ans[c[x].pos]+=siz[veranc]-siz[ver];
else{
int mid=0;
if((dep[ver]-dep[x]+c[ver].dis-c[x].dis)&1) mid=dep[ver]-(((dep[x]+dep[ver]+c[ver].dis-c[x].dis)>>1)+1);
else if(c[x].pos<c[ver].pos) mid=dep[ver]-(((dep[x]+dep[ver]+c[ver].dis-c[x].dis)>>1)+1);
else mid=dep[ver]-((dep[x]+dep[ver]+c[ver].dis-c[x].dis)>>1);
mid=climb(ver,mid);
ans[c[x].pos]+=siz[veranc]-siz[mid];
ans[c[ver].pos]+=siz[mid]-siz[ver];
}
}
}
/*
const int MAXN=3e5+5;
int n,q,ecnt,head[MAXN];
int tot,id[MAXN],num[MAXN],len,st[MAXN<<1][21],pos[MAXN];
int dep[MAXN],siz[MAXN],anc[MAXN][21];
int m,mm,h[MAXN<<1],hh[MAXN],top,sta[MAXN];
int iecnt,ihead[MAXN];
int ans[MAXN];
bool isc[MAXN];
*/
void clear_itree(){
iecnt=0;
rin(i,1,m) ihead[h[i]]=ans[h[i]]=0,isc[h[i]]=false;
}
int main(){
n=read();
rin(i,2,n){
int u=read(),v=read();
add_edge(u,v);
add_edge(v,u);
}
dfs1(1,0,1);
buildst();
buildanc();
q=read();
while(q--){
m=mm=read();
rin(i,1,m) h[i]=hh[i]=read(),isc[h[i]]=true;
build_itree();
dfs2(1);
dfs3(1,0);
dfs4(1,0);
rin(i,1,mm) printf("%d ",ans[hh[i]]);
putchar('\n');
clear_itree();
}
return 0;
}
[BZO3572][HNOI2014]世界树:虚树+倍增的更多相关文章
- 【BZOJ】3572: [Hnoi2014]世界树 虚树+倍增
[题意]给定n个点的树,m次询问,每次给定ki个特殊点,一个点会被最近的特殊点控制,询问每个特殊点控制多少点.n,m,Σki<=300000. [算法]虚树+倍增 [题解]★参考:thy_asd ...
- bzoj3572[Hnoi2014] 世界树 虚树+dp+倍增
[Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1921 Solved: 1019[Submit][Status][Dis ...
- BZOJ 3572: [Hnoi2014]世界树 [虚树 DP 倍增]
传送门 题意: 一棵树,多次询问,给出$m$个点,求有几个点到给定点最近 写了一晚上... 当然要建虚树了,但是怎么$DP$啊 大爷题解传送门 我们先求出到虚树上某个点最近的关键点 然后枚举所有的边$ ...
- 【BZOJ3572】[Hnoi2014]世界树 虚树
[BZOJ3572][Hnoi2014]世界树 Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森 ...
- bzoj 3572: [Hnoi2014]世界树 虚树 && AC500
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 520 Solved: 300[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的代码,不会写 ...
- 洛谷 P3233 [HNOI2014]世界树(虚树+dp)
题面 luogu 题解 数据范围已经告诉我们是虚树了,考虑如何在虚树上面\(dp\) 以下摘自hzwer博客: 构建虚树以后两遍dp处理出虚树上每个点最近的议事处 然后枚举虚树上每一条边,考虑其对两端 ...
- bzoj 3572: [Hnoi2014]世界树 虚树
题目: Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生 ...
- BZOJ 3572 [HNOI2014]世界树 (虚树+DP)
题面:BZOJ传送门 洛谷传送门 题目大意:略 细节贼多的虚树$DP$ 先考虑只有一次询问的情况 一个节点$x$可能被它子树内的一个到x距离最小的特殊点管辖,还可能被管辖fa[x]的特殊点管辖 跑两次 ...
随机推荐
- [DS+Algo] 011 哈希
目录 1. hash 函数 2. 哈希表 3. 密码存储 1. hash 函数 关键词 任意长度输入 固定长度输出 特征 理论上输入跟输出并不是一对一 实际使用假定不会出现碰撞或者冲突 常用算法 (M ...
- IDEA下集成tomcat7插件将tomcat内嵌到web项目中
新建一个maven web项目 修改pom.xml文件 <build> <plugins> <!-- 配置Tomcat插件: 就是本地部署,将tomcat 内嵌到 web ...
- django 商城项目之购物车以及python中的一些redis命令
最近在用django restframe框架做一个商城项目,有一个关于购物车的业务逻辑,是用cookie和redis存储的购物车信息,在这里记录一下. 完成一个商城项目,如果不做一个购物车,就是十分可 ...
- 开源消息服务中间件ActiveMQ安装部署
1.下载ActiveMQ 去官方网站下载:http://activemq.apache.org/ 2.运行ActiveMQ 解压缩apache-activemq-5.5.1-bin.zip 启动Act ...
- phpstudy配置多站点
1.打开vhosts.conf文件 目录 Apache/conf/vhosts.conf #开启apache的vhost模块 (此模块默认是关闭的,去掉前面的#号) LoadModule vh ...
- css实现div水平垂直居中
中秋快到了,祝大家中秋快乐. 平时大家写bug过程中肯定会遇到让div框水平或者垂直居中,然而有时候能居中,有时候不能居中.我把平时遇到的一些方法写出来,如果对你有用,那便是晴天. 1.text-al ...
- 解决echarts内存泄露的问题
clear方法和dispose方法 一种是调用clear方法,一种是dispose方法.第一种是清理echarts 但是不销毁实例.第二种是销毁实例,再次使用需要重新构建实例 1. var chart ...
- 新手 vim常用命令总结 (转)
转自 https://www.cnblogs.com/yangjig/p/6014198.html 在命令状态下对当前行用== (连按=两次), 或对多行用n==(n是自然数)表示自动缩进从当前行起的 ...
- C++ STL(二)vector的用法
##### vector的定义 ```#include <iostream>#include <string>#include <vector>using name ...
- 区块链共识算法|RAFT和PBFT的区别
这里有个很形象的比喻: 一个团队一定会有一个老大和普通成员.对于 raft 算法,共识过程就是:只要老大还没挂,老大说什么,我们(团队普通成员)就做什么,坚决执行.那什么时候重新老大呢?只有当老大挂了 ...