当前位置: 代码迷 >> 综合 >> Codeforces Round #483 (Div. 1) [Thanks, Botan Investments and Victor Shaburov#!] E. NN country
  详细解决方案

Codeforces Round #483 (Div. 1) [Thanks, Botan Investments and Victor Shaburov#!] E. NN country

热度:54   发布时间:2023-10-29 06:18:49.0

题意

自己看。。

题解

我们可以记录一下,每一个点通过公交线可以到的深度最小的点
然后显然地,如果一个点,他往上跳一下,还在LCA下面,那么肯定是继续跳的
这个过程可以用倍增加速
然后现在就是两个点,他们任意一个跳都会跳过LCA
那么最小就是还要两步
我们只需要考虑是否存在一条线路同时过这两个点就可以了
然后这条线路肯定是过LCA的
然后考虑怎么样的线路是合法的
肯定是LCA是这个点。然后两个点分别在两个子树里面
然后转化为dfs序就是一个在LCA里面矩阵数点的问题了
如果有点,那么就是+1,否则就是+2
CODE:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int MAX=(1<<30);
const int N=200005;
struct qq {int x,y,last; }e[N];
int num,last[N];
int n,m,q;
void init (int x,int y)
{num++;e[num].x=x;e[num].y=y;e[num].last=last[x];last[x]=num;
}
int Fa[N][21];
int dep[N];
int L[N],R[N],cnt;
void dfs (int x)
{L[x]=++cnt;for (int u=1;u<=20;u++) Fa[x][u]=Fa[Fa[x][u-1]][u-1];for (int u=last[x];u!=-1;u=e[u].last){int y=e[u].y;Fa[y][0]=x;dep[y]=dep[x]+1;dfs(y);}R[x]=cnt;
}
int get_lca (int x,int y)
{if (dep[x]<dep[y]) swap(x,y);for (int u=20;u>=0;u--)if (Fa[x][u]!=0&&dep[Fa[x][u]]>=dep[y])x=Fa[x][u];if (x==y) return x;for (int u=20;u>=0;u--)if (Fa[x][u]!=Fa[y][u]){
   x=Fa[x][u];y=Fa[y][u];}return Fa[x][0];
}
struct qt
{int id;//这是加点还是询问 int x,y;//如果是加点那么这个就是坐标,如果这个是询问,那么就是哪两个到吗 qt () {};qt (int _id,int _x,int _y)  {id=_id;x=_x;y=_y;}
};
vector<qt> s[N];
int low[N];
int fa[N][21];
int pow[21];
void update (int x,int y)
{//printf("%d %d %d %d\n",x,y,dep[low[x]],dep[y]);if (dep[low[x]]>dep[y]) low[x]=y;
}
void dfs1 (int x)
{for (int u=last[x];u!=-1;u=e[u].last){int y=e[u].y;dfs1(y);update(x,low[y]);}
}
void dfs2 (int x)
{fa[x][0]=low[x];for (int u=1;u<=20;u++) fa[x][u]=fa[fa[x][u-1]][u-1];for (int u=last[x];u!=-1;u=e[u].last){int y=e[u].y;dfs2(y);}
}
int ans[N];
struct qy
{int x,y;
}t[N];
void solve (int x,int y,int id)
{int o=get_lca(x,y);if (x==y) return ;for (int u=20;u>=0;u--){if (u!=0&&fa[x][u]==fa[x][u-1]) continue;int xx=fa[x][u];if (dep[xx]>dep[o]) {ans[id]=ans[id]+pow[u];x=xx;}}for (int u=20;u>=0;u--){if (u!=0&&fa[y][u]==fa[y][u-1]) continue;int xx=fa[y][u];if (dep[xx]>dep[o]) {ans[id]=ans[id]+pow[u];y=xx;}}if (dep[low[x]]>dep[o]||dep[low[y]]>dep[o]){ans[id]=-1;return ;}if (x==o||y==o)//如果一开始有一个lca {ans[id]++;return ;}if (L[x]>L[y]) swap(x,y);//printf("%d %d %d\n",o,x,y);s[o].push_back(qt(id,x,y));
}
int f[N];
int lb (int x)  {
   return x&(-x);}
void change (int x,int y)
{while (x<=n){f[x]+=y;x=x+lb(x);}
}
int find (int x)
{int lalal=0;while (x>=1){lalal=lalal+f[x];x=x-lb(x);}return lalal;
}
qt o[N*4];
int h[N];
bool cmp (qt x,qt y)    
{if (x.x==y.x) return (x.id==0);else return x.x<y.x;
}
int main()
{pow[0]=1;   for (int u=1;u<=20;u++) pow[u]=(pow[u-1]<<1);num=0;memset(last,-1,sizeof(last));scanf("%d",&n);for (int u=2;u<=n;u++){int x;scanf("%d",&x);init(x,u);}dep[0]=MAX;dfs(1);scanf("%d",&m);for (int u=1;u<=m;u++){int x,y;scanf("%d%d",&x,&y);int xx=get_lca(x,y);//printf("%d\n",xx);if (L[x]>L[y]) swap(x,y);//人为地让小的作为x坐标 s[xx].push_back(qt(-1,L[x],L[y]));update(x,xx);update(y,xx);}dfs1(1);dfs2(1);/*for (int u=1;u<=n;u++) printf("%d ",low[u]);printf("\n");*/scanf("%d",&q);for (int u=1;u<=q;u++){int x,y;scanf("%d%d",&x,&y);solve(x,y,u);}for (int u=1;u<=n;u++){int t=s[u].size();cnt=0;for (int i=0;i<t;i++){//  printf("%d %d %d\n",s[u][i].x,s[u][i].y,s[u][i].id);if (s[u][i].id==-1){o[++cnt]=qt(0,s[u][i].x,s[u][i].y);}else{int x=s[u][i].x,y=s[u][i].y,id=s[u][i].id;o[++cnt]=qt(id,R[x],R[y]);o[++cnt]=qt(-id,L[x]-1,R[y]);o[++cnt]=qt(-id,R[x],L[y]-1);o[++cnt]=qt(id,L[x]-1,L[y]-1);}}sort(o+1,o+1+cnt,cmp);//  for (int i=1;i<=cnt;i++) printf("YES:%d %d %d\n",o[i].id,o[i].x,o[i].y);for (int i=1;i<=cnt;i++){if (o[i].id==0) change(o[i].y,1);else{if (o[i].id>0){//  printf("OZY:%d %d\n",find(o[i].y));h[o[i].id]=h[o[i].id]+find(o[i].y);}else{//  printf("OZY:%d %d\n",find(o[i].y));h[-o[i].id]=h[-o[i].id]-find(o[i].y);}}}for (int i=0;i<t;i++){int id=s[u][i].id;if (id==-1) change(s[u][i].y,-1);else{if (h[id]>0) ans[id]++;else ans[id]=ans[id]+2;}}}for (int u=1;u<=q;u++)printf("%d\n",ans[u]);return 0;
}
  相关解决方案