LOJ #2206. 「HNOI2014」世界樹(虛數,長鏈剖分O(1)求k級祖先)

題目
虛樹顯然,
一次從下到上dpdp求子樹內能到該點的最優的臨時議事處。
一次從上到下dpdp求子樹外能到點uu的父親的最優的臨時議事處。
然後兩個加一下除個二,
樹上找kk級祖先即可。
長鏈剖分O(1)O(1)kk級祖先:
O(nlogn)O(n\log n )預處理所有點的2j2^j級祖先。
再對於每個長鏈鏈頭,處理鏈頭向上長鏈長度級的父親數組gg
那麼我們對於求uukk級父親。
uu先跳2r2^r步,其中2rk<2r+12^r\le k<2^{r+1}
然後我們再跳k2rk-2^r步,到達點一定在現在的uu在的長鏈所記錄的gg或者就在這一條長鏈上,O(1)O(1)算即可。
這個過程除了預處理都是可以O(1)O(1)
但是好像沒有純樹剖快
AC Code\mathrm {AC \ Code}

#include<bits/stdc++.h>
#define maxn 300005
#define lim 19
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define ADJ(i,u) for(int i=info[u],v;i;i=Prev[i])
#define Ct const 
#define inf 0x3f3f3f3f
using namespace std;

char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
void read(int &res){char ch;
	for(;!isdigit(ch=getc()););
	for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}

int tg[maxn<<2],*g[maxn]={tg},f[lim][maxn],lg[maxn];
int info[maxn],Prev[maxn<<1],to[maxn<<1],cnt_e;
void Node(int u,int v){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v; }
int len[maxn],tp[maxn],sonz[maxn],sonl[maxn],sz[maxn],fa[maxn],dep[maxn],dfn[maxn];
void dfs(int u,int ff){
	dep[u]=dep[f[0][u]=fa[u]=ff]+(sz[u]=1);
	ADJ(i,u) if((v=to[i])^ff){
		dfs(v,u),sz[u]+=sz[v],(sz[v]>sz[sonz[u]]) && (sonz[u] = v);
		(len[v]>len[sonl[u]]) && (sonl[u] = v);
	}
	len[u]=len[sonl[u]]+1;
}
void dfs2(int u,int ff){
	dfn[u]=++dfn[0];
	*g[u]=u;
	ADJ(i,u) 
		if((v=to[i])^ff) 
			tp[v]=v==sonz[u]?tp[u]:v;
	if(int v=sonl[u]) g[v]=g[u]+1,dfs2(v,u);
	ADJ(i,u) 
		if((v=to[i])^ff && v^sonl[u]){
			g[v]=g[0]+len[v],g[0]+=2*len[v];
			for(int j=1,p=fa[v];j<=len[v] && p;j++,p=fa[p])
				*(g[v]-j)=p;
			dfs2(v,u);
		}
}
int LCA(int u,int v){
	for(;tp[u]^tp[v];u=fa[tp[u]]) if(dep[tp[u]]<dep[tp[v]]) swap(u,v);
	return dep[u]<dep[v]?u:v;
}
int getk(int u,int k){
	if(!k) return u;
	int t = lg[k];
	u = f[t][u];			                                                                                         
	return *(g[u] - (k-(1<<t)));
}
inline bool cmp(Ct int &u,Ct int &v){ return dfn[u] < dfn[v]; }

struct data{
	int a,b;data(int a=0,int b=0):a(a),b(b){}
	bool operator <(Ct data &B)Ct{ return a==B.a?b<B.b:a<B.a; }
	data operator +(Ct int &B)Ct{ return data(a+B,b); }
}dp[2][maxn],dpl[maxn],dpr[maxn];
int ont[maxn],ans[maxn],ts[maxn];
void ser(int u){
	if(ont[u]) dp[0][u]=data(0,u);
	else dp[0][u]=data(inf,0);
	ts[u]=0;
	ADJ(i,u){
		ser(v=to[i]);int w = dep[v] - dep[u];
		dp[0][u]=min(dp[0][u],dp[0][v]+w);
		ts[u] += sz[getk(v,w-1)];
	}
}
void ser2(int u,bool fl=0){
	static int q[maxn]={},R=0;
	int p=0;
	if(ont[u]) dp[1][u] = data(0,u);
	dpl[p] = dp[1][u];
	ADJ(i,u){
		v=to[i];
		dpl[v] = min(dpl[p],dp[0][v]+(dep[v]-dep[u]));
		p = q[++R] = v;
	}
	dpr[p=0]=dp[1][u];
	for(;R;){
		int v = q[R--];
		data t = min(dpr[p] , dpl[q[R]]);
		int H = min(max((t.a + dp[0][v].a + dep[v] - dep[u] - 1 + (dp[0][v].b < t.b)) / 2 - dp[0][v].a , -1) , dep[v] - dep[u] - 1);
		int TS=(H==-1 ? ts[v] : sz[getk(v,H)]),HS=sz[getk(v,dep[v]-dep[u]-1)];
		ans[dp[0][v].b] += TS - ts[v] , ans[t.b] += HS - TS;
	//	if(t.b==1) printf("%d %d %d %d %d %d %d %d %d %d %d\n",u,dp[0][v].b,dp[0][v].a,t.a,t.b,TS,ts[v],HS,ans[1],dep[v]-dep[u],t.a + dp[0][v].a + dep[v] - dep[u]);
		dpr[v] = min(dpr[p],dp[0][v]+(dep[v]-dep[u]));
		p = v;
		dp[1][v]=t+(dep[v]-dep[u]);
	}
	ADJ(i,u){
		v=to[i];
		ser2(v);
	}
	if(fl){
		ans[dp[0][u].b]+=sz[1]-ts[u];
	}
}

int main(){
	
//	/freopen("1.in","r",stdin);
	//freopen("1.out","w",stdout);
	
	int u,v,n,m;
	read(n);
	rep(i,1,n-1) read(u),read(v),Node(u,v),Node(v,u);
	dfs(1,0),g[1]=g[0],g[0]+=len[1]+1,dfs2(tp[1]=1,0);
	rep(j,1,lim-1) rep(i,1,n) f[j][i] = f[j-1][f[j-1][i]];
	rep(i,2,n) lg[i] = lg[i>>1]+1;lg[0]=-1;
	read(m);
	memset(info,0,sizeof info),cnt_e=0;
	static int q[maxn],ar[maxn],ay[maxn],pt[maxn],cnt=0,R=0,N;
	for(;m--;){
		read(N);
		rep(i,0,N-1) read(ar[i]),ay[i]=ar[i],ont[ar[i]]=1;
		sort(ar,ar+N,cmp);
		rep(i,0,N-1){
			if(R){ int t=LCA(ar[i],q[R]),p=0;
				for(;R&&dep[q[R]]>dep[t];p=q[R--]) if(p) Node(q[R],p);
				if(q[R]^t) q[++R]=pt[++cnt]=t;
				if(p) Node(q[R],p);}
			q[++R]=pt[++cnt]=ar[i];
		}
		for(int p=0;R;p=q[R--]) if(p) Node(q[R],p);
		ser(q[1]),dp[1][q[1]]=dp[0][q[1]],ser2(q[1],1);
		int sm = 0;
		rep(i,0,N-1) printf("%d%c",ans[ay[i]]," \n"[i==N-1]);
		for(;cnt;){
			int t=pt[cnt--];
			ont[t] = ans[t] = info[t] = 0;
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章