zoukankan      html  css  js  c++  java
  • 并不对劲的loj2050:p3248:[HNOI2016]树

    题目大意

    有一棵(n)个点的树,根为1号点,称它为“模板树”。
    有一棵初始和模板树相同的树,称它为“当前树”。
    对“当前树”有(m)次操作,每次操作给出两个数(x,y)表示将模板树中(x)及其子树复制下来并粘贴到模板树,该子树的根与点(y)连边,假设操作前“当前树”有(a)个点,“模板树”中(x)的子树大小为(b),则粘贴上去的(b)个点的标号按这棵子树在“模板树”中的标号从小到大的顺序依次标为(a+1,a+2,...,a+b)
    (m)次操作后,有(q)次询问,每次问“当前树”上两点间的距离。
    (n,m,qleq 10^5;)

    题解

    建另一棵树:对于每次操作,粘贴过去的子树的根向点(y)所在的树的“根”连边(如果点(y)是之前的某一次粘贴过去的点,那么它的“根”是粘贴过去时子树的根,而不是整棵树的根)。
    询问两点距离时分类讨论它们是不是同一次粘贴过去的。如果是就直接在模板树上求,如果不是就让它们分别走到和它们同一次粘贴过去的子树的根,再在新树中求LCA。

    代码
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
    #define view(u,k) for(int k=fir[u];~k;k=nxt[k])
    #define maxn 100007
    #define maxnd 2000007
    #define LL long long
    #define pll pair<LL,LL>
    #define fi first
    #define se second
    #define mp make_pair
    #define ls ch[u][0]
    #define rs ch[u][1]
    #define mi ((l+r)>>1)
    using namespace std;
    LL read()
    {
    	LL x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)&&ch!='-')ch=getchar();
    	if(ch=='-')f=-1,ch=getchar();
    	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return x*f;
    }
    void write(LL x)
    {
    	if(x==0){putchar('0'),putchar('
    ');return;}
    	int f=0;char ch[20];
    	if(x<0)putchar('-'),x=-x;
    	while(x)ch[++f]=x%10+'0',x/=10;
    	while(f)putchar(ch[f--]);
    	putchar('
    ');
    	return;
    }
    struct nd{LL fa,start;int bac;}ad[maxn];
    LL nowsiz,qu[maxn],qv[maxn],dis[maxn][20];
    vector<pll>qx[maxn];
    int rt[maxn],ch[maxnd][2],num[maxnd],siz[maxn],cntnd,cntad,cnte,dep2[maxn];
    int n,m,q,fir[maxn],nxt[maxn<<1],v[maxn<<1],st[20][maxn<<1],tim,dfn[maxn],lg[maxn<<1],dep[maxn],anc[maxn][20];
    map<LL,int>to;
    void ade(int u1,int v1){v[cnte]=v1,nxt[cnte]=fir[u1],fir[u1]=cnte++;}
    void getdfn(int u)
    {
    	st[0][++tim]=u,dfn[u]=tim,siz[u]=1;
    	view(u,k)if(!dep[v[k]]&&v[k]!=1){dep[v[k]]=dep[u]+1,getdfn(v[k]),siz[u]+=siz[v[k]],st[0][++tim]=u;}
    }
    inline int lca(int x,int y)
    {
    	x=dfn[x],y=dfn[y];if(x>y)swap(x,y);
    	int len=y-x+1;return dep[st[lg[len]][x]]<dep[st[lg[len]][y-(1<<lg[len])+1]]?st[lg[len]][x]:st[lg[len]][y-(1<<lg[len])+1];
    }
    inline int Dis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}
    int getid(LL x)
    {
    	int L=1,R=m+1,res=-1;
    	while(L<=R)
    	{
    		int mid=(L+R)>>1;
    		if(ad[mid].start<=x)res=max(res,mid),L=mid+1;
    		else R=mid-1;
    	}
    	return res;
    }
    inline void pu(int u){num[u]=0;if(ls)num[u]+=num[ls];if(rs)num[u]+=num[rs];return;}
    int build(int l,int r,int x)
    {
    	int u=++cntnd;
    	if(x<=l&&r<=x){num[u]=1;return u;}
    	if(x<=mi)ls=build(l,mi,x);
    	else rs=build(mi+1,r,x);
    	num[u]=1;return u;
    }
    int merge(int u,int ub,int l,int r)
    {
    	if(!u||!ub){return u|ub;}
    	ls=merge(ls,ch[ub][0],l,mi);
    	rs=merge(rs,ch[ub][1],mi+1,r);
    	pu(u);return u;
    }
    int ask(int u,int l,int r,int x)
    {
    	if(l==r)return l;
    	if(!ls||num[ls]<x){x-=ls?num[ls]:0;return ask(rs,mi+1,r,x);}
    	return ask(ls,l,mi,x);
    }
    void getto(int u)
    {
    	rt[u]=build(1,n,u);
    	view(u,k)if(dep[v[k]]>dep[u]){getto(v[k]),rt[u]=merge(rt[u],rt[v[k]],1,n);}
    	int li=qx[u].size()-1;
    	rep(i,0,li){to[qx[u][i].fi]=ask(rt[u],1,n,qx[u][i].se);}
    }
    int main()
    {
    	n=read(),m=read(),q=read();
    	rep(i,1,n)fir[i]=-1;
    	rep(i,2,n){int x=read(),y=read();ade(x,y),ade(y,x);}
    	getdfn(1);lg[0]=-1;
    	rep(i,1,tim)lg[i]=lg[i>>1]+1;
    	rep(i,1,lg[tim])for(int j=1;j+(1<<i)-1<=tim;j++)
    		st[i][j]=dep[st[i-1][j]]<dep[st[i-1][j+(1<<(i-1))]]?st[i-1][j]:st[i-1][j+(1<<(i-1))]; 
    	ad[1].bac=1,ad[1].fa=0,ad[1].start=1,nowsiz=n;
    	rep(i,2,m+1)
    	{
    		int a=read();LL b=read();
    		ad[i].bac=a,ad[i].fa=b,ad[i].start=nowsiz+1,nowsiz+=siz[a];//cout<<siz[a]<<" "<<a<<endl;
    	}cntad=m;
    	rep(i,2,m+1){int id=getid(ad[i].fa);anc[i][0]=id;qx[ad[id].bac].push_back(mp(ad[i].fa,ad[i].fa-ad[id].start+1));}
    	rep(i,1,q)
    	{
    		qu[i]=read(),qv[i]=read();int idu=getid(qu[i]),idv=getid(qv[i]);
    		qx[ad[idu].bac].push_back(mp(qu[i],qu[i]-ad[idu].start+1)),
    		qx[ad[idv].bac].push_back(mp(qv[i],qv[i]-ad[idv].start+1));
    	}
    	getto(1);
    	rep(i,2,m+1)
    	{
    		dis[i][0]=Dis(ad[anc[i][0]].bac,to[ad[i].fa])+1,dep2[i]=dep2[anc[i][0]]+1;
    		rep(j,1,19)
    		{
    			anc[i][j]=anc[anc[i][j-1]][j-1];
    			dis[i][j]=dis[i][j-1]+dis[anc[i][j-1]][j-1];
    		}
    	}
    	rep(i,1,q)
    	{
    		LL ans=0,x=qu[i],y=qv[i],idx=getid(x),idy=getid(y);
    		if(idx==idy){ans=Dis(to[x],to[y]);}
    		else
    		{
    			if(dep2[idx]<dep2[idy])swap(idx,idy),swap(x,y);
    			dwn(i,19,0)if(anc[idx][i]&&dep2[anc[idx][i]]>dep2[idy])
    			{
    				if(x&&to[x]!=ad[idx].bac)ans+=Dis(to[x],ad[idx].bac);
    				ans+=dis[idx][i],idx=anc[idx][i],x=0;
    			}
    			if(anc[idx][0]==idy)
    			{
    				if(x&&to[x]!=ad[idx].bac)ans+=Dis(to[x],ad[idx].bac);x=0;
    				ans+=Dis(to[ad[idx].fa],to[y])+1;
    			}
    			else 
    			{
    				if(dep2[idx]>dep2[idy])
    				{
    					if(x&&to[x]!=ad[idx].bac)ans+=Dis(to[x],ad[idx].bac);
    					ans+=dis[idx][0],idx=anc[idx][0],x=0;
    				}
    				dwn(i,19,0)if(anc[idx][i]&&anc[idy][i]&&anc[idx][i]!=anc[idy][i])
    				{
    					if(x&&to[x]!=ad[idx].bac)ans+=Dis(to[x],ad[idx].bac);
    					if(y&&to[y]!=ad[idy].bac)ans+=Dis(to[y],ad[idy].bac);
    					ans+=dis[idx][i]+dis[idy][i],idx=anc[idx][i],idy=anc[idy][i];x=0,y=0;
    				}
    				if(x&&to[x]!=ad[idx].bac)ans+=Dis(to[x],ad[idx].bac);
    				if(y&&to[y]!=ad[idy].bac)ans+=Dis(to[y],ad[idy].bac);
    				ans+=Dis(to[ad[idx].fa],to[ad[idy].fa])+2;
    			}
    		}
    		write(ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Android文件操作说明

    d
    关于<验证码>的实现和执行流程 http://www.cnblogs.com/androidhtml5/archive/2012/05/19/2533650.html
    div 嵌套 图片
    在线FLV播放器实现方法
    转载 android webview js
    d
    d
    消息
  • 原文地址:https://www.cnblogs.com/xzyf/p/13092748.html
Copyright © 2011-2022 走看看