983E - NN country

Posted wang9897

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了983E - NN country相关的知识,希望对你有一定的参考价值。

http://codeforces.com/problemset/problem/983/E

题意:给定一棵树,给m个公交车路线,即从u到v可直达不用换乘,给q次查询,问从u,v最少需要多少次换乘

题解:考虑到查询操作我们可以分成两部分u->lca(u,v)->v,对于u->lca这段路我们找到t,即从t->lca只需要一次换乘,对于右边路径,我们需要找到一个点z,使得t->z有一次换乘的路径(通过主席树来维护t的子树和z的子树之间是否有直达路线),满足单调性,所以二分查找最合适的z,然后加上前半部分的贡献即为所求

#include <bits/stdc++.h>
#define ll long long
#define s second
#define f first
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=2e5+10;
const int K=20;
using namespace std;
vector<int>vec[MAXN];
int num[MAXN],son[MAXN],fa[MAXN],dep[MAXN],f[MAXN];
int st[MAXN][21];
int n,m,q;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
    return f*x;
}
void dfs1(int v,int pre,int deep){
	num[v]=1;fa[v]=pre;dep[v]=deep+1;
	for(int i=0;i<vec[v].size();i++){
		int u=vec[v][i];
		if(u!=pre){
			dfs1(u,v,deep+1);
			num[v]+=num[u];
			if(son[v]==-1||num[son[v]]<num[u])son[v]=u;
		}
	}
}
int p[MAXN],fp[MAXN],cnt,tp[MAXN],rt[MAXN];
void dfs2(int v,int td){
	p[v]=++cnt;fp[cnt]=v;tp[v]=td;
	if(son[v]!=-1) dfs2(son[v],td);
	for(int i=0;i<vec[v].size();i++)if(son[v]!=vec[v][i]&&vec[v][i]!=fa[v])dfs2(vec[v][i],vec[v][i]);
}
int Lca(int u,int v){
	int uu=tp[u];int vv=tp[v];
	while(uu!=vv){
		if(dep[uu]<dep[vv]) swap(uu,vv),swap(u,v);
		u=fa[uu];uu=tp[u];
	}
	if(dep[u]>dep[v]) swap(u,v);
	return u;
}
typedef struct node{
	int l,r,sum;
}node;
node d[MAXN*45];int cnt1;
int querty(int u,int v){
	if(u==v) return 0;
	if(dep[st[v][K]]>dep[u]) return -1;
	int ans1=1,t=v;
//	cout<<p[st[v][K]]<<" "<<p[u]<<endl;
	for(int i=K;i>=0;i--){
	if(dep[st[t][i]]>dep[u])ans1+=(1<<i),t=st[t][i];
//	cout<<p[st[t][i]]<<" "<<p[u]<<endl;
}
	return ans1;
}
void update(int &x,int y,int l,int r,int t){
//	cout<<l<<":::"<<r<<" "<<t<<endl;
	x=++cnt1;d[x]=d[y];d[x].sum++;
//	cout<<d[x].sum<<endl;
	if(l==r) return ;
	int mid=(l+r)>>1;
	if(t<=mid) update(d[x].l,d[y].l,l,mid,t);
	else update(d[x].r,d[y].r,mid+1,r,t);
}
int ans=0;
void Sum(int x,int y,int l,int r,int ql,int qr){
//	cout<<l<<" "<<r<<" "<<ans<<" "<<d[y].sum<<endl;
	if(ql<=l&&r<=qr){ans+=(d[y].sum-d[x].sum);return ;}
	int mid=(l+r)>>1;
	if(ql<=mid) Sum(d[x].l,d[y].l,l,mid,ql,qr);
	if(qr>mid) Sum(d[x].r,d[y].r,mid+1,r,ql,qr);
}
int erfen(int v,int mid){
	int vv=tp[v];
	while(1){
		int t=p[v]-p[vv];
		if(mid<=t) return fp[p[v]-mid];
		mid-=(t+1);v=fa[vv];vv=tp[v];
	}
}
bool check(int u,int v){if(p[v]>p[u])swap(v,u);ans=0;Sum(rt[p[v]-1],rt[p[v]+num[v]-1],1,n,p[u],p[u]+num[u]-1);return ans>0;}
int slove(int u,int v){
	if(u==v) return 0;
	int lca=Lca(u,v);
	if(lca==u||lca==v){
		if(dep[u]>dep[v]) swap(u,v);
		return querty(u,v);		
	}
	if(dep[st[u][K]]>dep[lca]) return -1;
	int ans3=0,t=u;
	for(int i=K;i>=0;i--)if(dep[st[t][i]]>dep[lca])ans3+=(1<<i),t=st[t][i];
//	cout<<ans3<<endl;
	int l=0;int r=dep[v]-dep[lca]-1;int z=dep[v]-dep[lca];
	//cout<<l<<" "<<r<<endl;
//	cout<<"::::"<<t<<endl;
	while(l<=r){
		int mid=(l+r)>>1;
	//	cout<<t<<"---"<<erfen(v,mid)<<endl;
//		cout<<l<<" "<<r<<" "<<erfen(v,mid)<<endl;
		if(check(t,erfen(v,mid)))z=mid,r=mid-1;
		else l=mid+1;
//		cout<<l<<" "<<r<<" "<<z<<endl;
	}
//	cout<<erfen(v,z)<<endl;
	int ttt=querty(erfen(v,z),v);
//	cout<<ans3<<" "<<ttt<<endl;
	if(ttt<0) return -1;
	ans3+=(ttt+1);
	return ans3;
}
int find1(int x){
//	cout<<x<<"----"<<endl;
	if(x==f[x]) return x;
	else return f[x]=find1(f[x]);
}
void dfs3(int v){
	for(int i=1;i<=K;i++) st[v][i]=st[st[v][i-1]][i-1];
	for(int i=0;i<vec[v].size();i++)if(vec[v][i]!=fa[v])dfs3(vec[v][i]);
}
void merge(int u,int v){
//	cout<<dep[u]<<" "<<dep[v]<<" "<<u<<" "<<v<<endl;
for(u=find1(u);dep[u]>=dep[v];u=find1(u))st[u][0]=v,f[u]=fa[u];
}
typedef struct Node{
	int x,y,z;
}Node;
Node que[MAXN];
bool cmp1(Node aa,Node bb){
	return dep[aa.z]<dep[bb.z];
}
bool cmp2(Node aa,Node bb){
	return p[aa.x]<p[bb.x];
}
int main(){
	n=read();
	//m=read();q=read();
	int u,v;cnt=cnt1=0;
	for(int i=1;i<=n;i++)son[i]=-1,st[i][0]=f[i]=i;
	//for(int i=1;i<n;i++)u=read(),v=read(),vec[u].push_back(v),vec[v].push_back(u);
	inc(i,2,n)u=read(),vec[i].push_back(u),vec[u].push_back(i);
	dfs1(1,0,0);dfs2(1,1);
//	for(int i=1;i<=n;i++) cout<<p[i]<<" ";
//	cout<<endl;
	m=read();
	for(int i=1;i<=m;i++){
	u=read();v=read();
	if(u==v) continue;
	que[i].x=u,que[i].y=v,que[i].z=Lca(que[i].x,que[i].y);
}
	sort(que+1,que+m+1,cmp1);
	for(int i=1;i<=m;i++)merge(que[i].x,que[i].z),merge(que[i].y,que[i].z);
	for(int i=1;i<=m;i++)if(p[que[i].x]>p[que[i].y])swap(que[i].x,que[i].y);
//	cout<<"sb"<<endl;
//	for(int i=1;i<=n;i++) cout<<st[i][0]<<" ";
//	cout<<endl;
	dfs3(1);
	sort(que+1,que+1+m,cmp2);int t=1;
	for(int i=1;i<=cnt;i++){
		rt[i]=rt[i-1];
		for(;p[que[t].x]==i;t++)update(rt[i],rt[i],1,n,p[que[t].y]);
//		ans=0;Sum(rt[3],rt[4],1,n,5,6);
//		cout<<ans<<"==---"<<endl;
	}
//		ans=0;Sum(rt[3],rt[4],1,n,5,6);
//		cout<<ans<<"==---"<<endl;
//	cout<<"sb"<<endl;
	q=read();
	while(q--){
		u=read();v=read();
		int ans2=slove(u,v);
		if(ans2<0) puts("-1");
		else printf("%d\n",ans2);
	}
	return 0;
}

  

以上是关于983E - NN country的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 983E NN country 思维 (看题解)

CF983E NN country [倍增][LCA][树状数组]

题解CF#983 E-NN country

中继现代片段错误(期望对象包含数据....)

97: cf 983E 倍增+树套树

RexNet片段记录