cf983E NN Country (倍增+dfs序+树状数组)

首先可以求出从某点做$2^k$次车能到的最浅的点,这个只要dfs一下,把它的孩子能到的最浅的点更新过来就可以

然后倍增地往上跳,不能跳到lca的上面,记录坐车的次数ans

此时有三种情况(设最远能跳到x,y):

  1.再跳也跳不到lca的上面,就是-1

  2.路径(x,y)被某趟车覆盖,答案是ans+1

  3.并没有被覆盖,答案是ans+2

那么怎么看有没有覆盖呢

首先,如果这两个点是直上直下的(有一个是lca),只要看下面那个点能不能跳到上面去就行

对于剩下的(x,y),只要有车的两端点分别在x和y的子树中就可以

所以做一遍dfs,进某个点x的时候记下来y的子树中车端点的个数,然后把从x发的车的终点++,出来的时候再次统计那个个数,如果不相同,就说明(x,y)这条路径被覆盖了。这个在dfs序上用一个树状数组就可以

不要把N写成M然后WA一页,很难看。

  1 #include<bits/stdc++.h>
  2 #define pa pair<int,int>
  3 #define CLR(a,x) memset(a,x,sizeof(a))
  4 using namespace std;
  5 typedef long long ll;
  6 const int maxn=2e5+10;
  7 
  8 inline ll rd(){
  9     ll x=0;char c=getchar();int neg=1;
 10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
 11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
 12     return x*neg;
 13 }
 14 
 15 int eg[maxn][2],egh[maxn],ect;
 16 int N,M,Q,dep[maxn],fa[maxn][22],nxt[maxn][22];
 17 int dfn[maxn][2],tot,ans[maxn];
 18 int pt[maxn*2][2],pth[maxn],tr[maxn];
 19 int lq[maxn*2][2],lqh[maxn],tmp[maxn*2];
 20 bool covered[maxn];
 21 
 22 inline void adeg(int a,int b){
 23     eg[++ect][0]=b,eg[ect][1]=egh[a],egh[a]=ect;
 24 }
 25 
 26 void dfs(int x){
 27     dfn[x][0]=++tot;
 28     for(int i=0;fa[x][i]&&fa[fa[x][i]][i];i++)
 29         fa[x][i+1]=fa[fa[x][i]][i];
 30     for(int i=egh[x];i;i=eg[i][1]){
 31         int b=eg[i][0];
 32         dep[b]=dep[x]+1;
 33         dfs(b);
 34     }dfn[x][1]=tot;
 35 }
 36 
 37 int getlca(int x,int y){
 38     if(dep[x]<dep[y]) swap(x,y);
 39     for(int i=19;i>=0&&dep[x]!=dep[y];i--){
 40         if(fa[x][i]&&dep[fa[x][i]]>=dep[y])
 41             x=fa[x][i];
 42     }
 43     if(x==y) return x;
 44     for(int i=19;i>=0;i--){
 45         if(fa[x][i]!=fa[y][i])
 46             x=fa[x][i],y=fa[y][i];
 47     }
 48     return fa[x][0];
 49 }
 50 
 51 void dfs2(int x){
 52     for(int i=egh[x];i;i=eg[i][1]){
 53         int b=eg[i][0];
 54         dfs2(b);
 55         if(nxt[b][0]&&(dep[nxt[b][0]]<dep[nxt[x][0]]||!nxt[x][0]))
 56             nxt[x][0]=nxt[b][0];
 57     }
 58     if(dep[nxt[x][0]]>=dep[x]) nxt[x][0]=0;
 59 }
 60 
 61 inline int lowbit(int x){return x&(-x);}
 62 inline void add(int x,int y){
 63     for(;x<=N;x+=lowbit(x)) tr[x]+=y;
 64 }
 65 inline int query(int x){
 66     int re=0;for(;x;x-=lowbit(x)) re+=tr[x];return re;
 67 }
 68 
 69 void dfs3(int x){
 70     for(int i=lqh[x];i;i=lq[i][1]){
 71         int b=lq[i][0];
 72         tmp[i]=query(dfn[b][1])-query(dfn[b][0]-1);
 73     }
 74     for(int i=pth[x];i;i=pt[i][1]){
 75         int b=pt[i][0];
 76         add(dfn[b][0],1);
 77     }
 78     for(int i=egh[x];i;i=eg[i][1]){
 79         int b=eg[i][0];
 80         dfs3(b);
 81     }
 82     for(int i=lqh[x];i;i=lq[i][1]){
 83         int b=lq[i][0];
 84         if(tmp[i]!=query(dfn[b][1])-query(dfn[b][0]-1))
 85             covered[i>>1]=1;
 86     }
 87 }
 88 
 89 int main(){
 90     // freopen("983E.in","r",stdin);
 91     int i,j,k;
 92     N=rd();
 93     for(i=2;i<=N;i++){
 94         fa[i][0]=rd();
 95         adeg(fa[i][0],i);
 96     }
 97     dep[1]=1;dfs(1);
 98     M=rd();
 99     for(i=1;i<=M;i++){
100         int a=rd(),b=rd();
101         pt[i<<1][0]=a,pt[i<<1][1]=pth[b],pth[b]=i<<1;
102         pt[i<<1|1][0]=b,pt[i<<1|1][1]=pth[a],pth[a]=i<<1|1;
103         int x=getlca(a,b);
104         if(dep[x]<dep[nxt[a][0]]||!nxt[a][0]) nxt[a][0]=x;
105         if(dep[x]<dep[nxt[b][0]]||!nxt[b][0]) nxt[b][0]=x;
106     }
107     dfs2(1);
108     for(i=0;i<19;i++){
109         for(j=1;j<=N;j++){
110             // if(!nxt[j][i]||!nxt[nxt[j][i]][i]) continue;
111             nxt[j][i+1]=nxt[nxt[j][i]][i];
112         }
113     }
114     Q=rd();
115     for(i=1;i<=Q;i++){
116         int a=rd(),b=rd(),lca=getlca(a,b);
117         for(j=19;j>=0;j--){
118             if(nxt[a][j]&&dep[nxt[a][j]]>dep[lca])
119                 ans[i]+=1<<j,a=nxt[a][j];
120         }
121         for(j=19;j>=0;j--){
122             if(nxt[b][j]&&dep[nxt[b][j]]>dep[lca])
123                 ans[i]+=1<<j,b=nxt[b][j];
124         }
125         if((a==lca&&nxt[b][0]&&dep[nxt[b][0]]<=dep[lca])||(b==lca&&nxt[a][0]&&dep[nxt[a][0]]<=dep[lca]))
126             ans[i]+=1;
127         else if(nxt[a][0]&&nxt[b][0]&&dep[nxt[a][0]]<=dep[lca]&&dep[nxt[b][0]]<=dep[lca]){
128             ans[i]+=2;
129             lq[i<<1][0]=a,lq[i<<1][1]=lqh[b],lqh[b]=i<<1;
130             lq[i<<1|1][0]=b,lq[i<<1|1][1]=lqh[a],lqh[a]=i<<1|1;
131         }else{
132             ans[i]=-1;
133         }
134     }
135     dfs3(1);
136     for(i=1;i<=Q;i++)
137         printf("%d\n",ans[i]-covered[i]);
138     return 0;
139 }

 

转载于:https://www.cnblogs.com/Ressed/p/9811477.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值