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('
');dcnt=cnt=0;
	}
}
int main()
{
	read(n);
	yuucute::init();
	read(q);
	while(q--) yuulovely::work();
	return 0;
}

2019.2.20

原文地址:https://www.cnblogs.com/butterflydew/p/10407969.html