• 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

  • 相关阅读:
    Notepad++ 6.2.3 发布,开源文本编辑器
    Scrum项目如何获得管理层的支持和合作
    Concurrency Kit 0.2.13 发布,并发工具包
    Orubase:为Windows Phone、Android和iOS平台开发混合本地手机应用程序
    CyaSSL 2.4.6 发布,SSL 加密库
    谷歌移动应用强调设计元素:向极简风格转型
    Bitcoin 0.7.2 发布, 匿名数字货币
    Netty 3.5.11 发布
    LDAP Account Manager 4.0 发布
    Apache Commons Math 3.1 发布
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10407969.html
Copyright © 2020-2023  润新知