HNOI 2014 世界树
HNOI 2014 世界树
先建出虚树,然后求出虚树上每个点归谁管。
然后再求出虚树上每个点的实际管辖大小。
具体的,对虚树上每条边,用倍增跳到它们的中间点,然后划分一下就可以了。
最开始有个东西没请空,结果T了,然后卡了一万年的常数...
Code:
#include <cstdio>
#include <cctype>
#include <algorithm>
const int N=3e5+10;
int n,q;
namespace io
{
const int SIZE=(1<<21)+1;
char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55];
int f,qr;
// getchar
#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
// print the remaining part
inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
// putchar
inline void putc(char x){*oS++=x;if(oS==oT)flush();}
// input a signed integer
template <class I>
inline void read(I &x)
{
for(f=1,c=gc();c<'0'||c>'9';c=gc()) if(c=='-') f=-1;
for(x=0;c<='9'&&c>='0';c=gc()) x=x*10+(c&15);x*=f;
}
// print a signed integer
template <class I>
inline void print(I &x)
{
if(!x)putc('0');if(x<0) putc('-'),x=-x;
while(x)qu[++qr]=x%10+'0',x/=10;
while(qr)putc(qu[qr--]);
}
//no need to call flush at the end manually
struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io::read;
using io::putc;
using io::print;
namespace yuucute
{
int head[N],to[N<<1],Next[N<<1],cnt;
void add(int u,int v){to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;}
int dfn[N],siz[N],dep[N],f[20][N],st[20][N<<1],Log[N<<1],dfsclock;
void dfs(int now,int fa)
{
dep[st[0][dfn[now]=++dfsclock]=now]=dep[fa]+1,siz[now]=1;
for(int i=1;f[i-1][now];i++) f[i][now]=f[i-1][f[i-1][now]];
for(int v,i=head[now];i;i=Next[i])
if((v=to[i])!=fa)
dfs(v,f[0][v]=now),st[0][++dfsclock]=now,siz[now]+=siz[v];
}
void init()
{
for(int u,v,i=1;i<n;i++)
read(u),read(v),add(u,v),add(v,u);
dfs(1,0);
for(int i=2;i<=dfsclock;i++) Log[i]=Log[i>>1]+1;
for(int j=1;j<=19;j++)
for(int i=1;i<=dfsclock-(1<<j)+1;i++)
{
int x=st[j-1][i],y=st[j-1][i+(1<<j-1)];
st[j][i]=dep[x]<dep[y]?x:y;
}
}
int LCA(int x,int y)
{
x=dfn[x],y=dfn[y];
if(x>y) std::swap(x,y);
int d=Log[y+1-x];
x=st[d][x],y=st[d][y-(1<<d)+1];
return dep[x]<dep[y]?x:y;
}
int Dis(int x,int y){return dep[x]+dep[y]-(dep[LCA(x,y)]<<1);}
int get(int x,int y,int k,int dx,int dy)//k=1 => x>y
{
int d=Dis(x,y)+dx+dy,ct=0;
k=(d>>1)-(d+1&k)-dx;
while(k)
{
if(k&1) x=f[ct][x];
k>>=1,++ct;
}
return x;
}
}
namespace yuulovely
{
//using yuucute::dfn;
//using yuucute::siz;
//using yuucute::Dis;
#define dfn yuucute::dfn
#define siz yuucute::siz
#define Dis yuucute::Dis
int head[N],to[N],Next[N],cnt;
void add(int u,int v){to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;}
int s[N],tot,del[N],dcnt,is[N],bel[N],ans[N],sum[N],pos[N],dis[N];
struct node
{
int x,id;
bool friend operator <(node a,node b){return dfn[a.x]<dfn[b.x];}
}pot[N];
void ins(int now)
{
int lca=yuucute::LCA(now,s[tot]);
while(tot>1&&dfn[s[tot-1]]>dfn[lca]) add(s[tot-1],s[tot]),--tot;
if(lca==s[tot]) {s[++tot]=now;return;}
add(lca,s[tot--]);
if(s[tot]!=lca) s[++tot]=lca;
s[++tot]=now;
}
bool ck(int now,int a,int b)//now \in a => true
{
int x=Dis(now,a),y=Dis(now,b);
return x==y?a<b:x<y;
}
void dfs1(int now)
{
del[++dcnt]=now;
if(is[now]) bel[now]=now;
for(int v,i=head[now];i;i=Next[i])
{
dfs1(v=to[i]);
if(!bel[now]||ck(now,bel[v],bel[now])) bel[now]=bel[v];
}
}
void dfs2(int now,int fa)
{
if(!bel[now]||(fa&&ck(now,bel[fa],bel[now]))) bel[now]=bel[fa];
for(int i=head[now];i;i=Next[i]) dfs2(to[i],now);
}
void dfs(int now)
{
ans[now]=siz[now];
for(int v,i=head[now];i;i=Next[i])
{
dfs(v=to[i]);
ans[now]-=siz[v];
if(bel[now]==bel[v]) continue;
int w=yuucute::get(v,now,bel[v]>bel[now],dis[v],dis[now]);
ans[v]+=siz[w]-siz[v];
ans[now]-=siz[w]-siz[v];
}
}
void work()
{
int m;read(m);
for(int i=1;i<=m;i++) read(pot[i].x),is[pot[i].x]=1,pot[i].id=i;
std::sort(pot+1,pot+1+m);
for(int i=1;i<=m;i++) pos[pot[i].x]=pot[i].id;
s[tot=1]=1;
for(int i=1+is[1];i<=m;i++)
ins(pot[i].x);
while(tot>1) add(s[tot-1],s[tot]),--tot;
dfs1(1);
dfs2(1,0);
for(int x,i=1;i<=dcnt;i++) x=del[i],dis[x]=Dis(x,bel[x]);
dfs(1);
for(int i=1;i<=dcnt;i++)
{
int x=del[i];
sum[pos[bel[x]]]+=ans[x];
is[x]=bel[x]=head[x]=0;
}
for(int i=1;i<=m;i++) print(sum[i]),putc(' '),sum[i]=0;
putc('\n');dcnt=cnt=0;
}
}
int main()
{
read(n);
yuucute::init();
read(q);
while(q--) yuulovely::work();
return 0;
}
2019.2.20