CF983E NN country(倍增,差分)
题意
给定一棵树和若干条路线,每条路线相当于树上 x,y 之间的路径,途径路径上的每个点
给出若干个询问,每次询问从 u 到 v 至少需要利用几条路线
N,M,Q≤200000
题解
构建倍增数组g[i][j]表示从i点向上经过j条线路能到达的深度最小的点。
所以对于每一对询问的x,y,我们贪心地把它们提到深度大于等于lca地最大的点。记为x‘,y'然后判断是否有路径经过x’和y‘
然后各种情况特判(无解,x‘,y’为lca,有无路径经过x‘,y’)
然后对于判断是否路径经过x‘,y’。
可以用树状数组维护 DFS 序
DFS 遍历整棵树,递归进入 x 时,扫描路线 (x,y),把 y 在 DFS 序上对应位置 +1,
x,y 可直达,当且仅当 x 子树中的节点使 DFS 序上 y 对应区间的和发生了变化
(调了半天代码最后没调出来,最后屈辱地看了题解)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<vector> 7 using namespace std; 8 const int N=200005; 9 const int D=30; 10 struct node{ 11 int a,b; 12 }; 13 vector<int> road[N],h[N]; 14 vector<node> q[N]; 15 int n,m,t,fa[N][D+1],w[N][D+1],head[N],sum[N],ans[N],g[N]; 16 int cnt,tot,dep[N],id[N],size[N],c[N]; 17 int lowbit(int x){ 18 return x&-x; 19 } 20 void update(int x){ 21 for(int i=x;i<=n;i+=lowbit(i)){ 22 c[i]+=1; 23 } 24 } 25 int check(int x){ 26 int tmp=0; 27 for(int i=x;i>=1;i-=lowbit(i)){ 28 tmp+=c[i]; 29 } 30 return tmp; 31 } 32 struct edge{ 33 int to,nxt; 34 }e[N*2]; 35 void add(int u,int v){ 36 cnt++; 37 e[cnt].nxt=head[u]; 38 e[cnt].to=v; 39 head[u]=cnt; 40 } 41 void dfs1(int u,int deep){ 42 dep[u]=deep; 43 id[u]=++tot; 44 size[u]=1; 45 for(int i=head[u];i;i=e[i].nxt){ 46 int v=e[i].to; 47 if(v==fa[u][0])continue; 48 dfs1(v,deep+1); 49 size[u]+=size[v]; 50 } 51 } 52 void dfs2(int u){ 53 g[u]=u; 54 // cout<<u<<"ksdjfksdf"<<endl; 55 for(int i=0;i<h[u].size();i++){ 56 // cout<<h[u][i]<<endl; 57 if(dep[h[u][i]]<dep[g[u]])g[u]=h[u][i]; 58 } 59 for(int i=head[u];i;i=e[i].nxt){ 60 int v=e[i].to; 61 // cout<<v<<" "<<fa[u][0]<<endl; 62 if(v==fa[u][0])continue; 63 dfs2(v); 64 if(dep[g[v]]<dep[g[u]])g[u]=g[v]; 65 } 66 w[u][0]=g[u]; 67 } 68 int lca(int x,int y){ 69 if(dep[x]<dep[y])swap(x,y); 70 for(int i=D;i>=0;i--){ 71 if(dep[fa[x][i]]>=dep[y])x=fa[x][i]; 72 } 73 if(x==y)return x; 74 for(int i=D;i>=0;i--){ 75 if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i]; 76 } 77 return fa[x][0]; 78 } 79 node work(int x,int LCA){ 80 if(x==LCA)return (node){x,0}; 81 int tmp=0; 82 for(int i=D;i>=0;i--) 83 if(dep[w[x][i]]>dep[LCA])x=w[x][i],tmp+=(1<<i); 84 if(w[x][0]==x)return (node){x,-1}; 85 return (node){x,tmp}; 86 } 87 int main(){ 88 scanf("%d",&n); 89 for(int i=2;i<=n;i++){ 90 scanf("%d",&fa[i][0]); 91 add(fa[i][0],i); 92 add(i,fa[i][0]); 93 } 94 dfs1(1,1); 95 for(int i=1;i<=D;i++) 96 for(int j=1;j<=n;j++){ 97 fa[j][i]=fa[fa[j][i-1]][i-1]; 98 } 99 scanf("%d",&m); 100 for(int i=1;i<=m;i++){ 101 int x,y; 102 scanf("%d%d",&x,&y); 103 int c=lca(x,y); 104 // cout<<c<<endl; 105 if(id[x]>id[y])swap(x,y); 106 road[id[x]].push_back(id[y]); 107 if(dep[c]<dep[x])h[x].push_back(c); 108 if(dep[c]<dep[y])h[y].push_back(c); 109 } 110 dfs2(1); 111 for(int i=1;i<=n;i++){ 112 // cout<<g[i]<<endl; 113 } 114 for(int i=1;i<=D;i++) 115 for(int j=1;j<=n;j++){ 116 w[j][i]=w[w[j][i-1]][i-1]; 117 // cout<<w[j][i]<<endl; 118 } 119 scanf("%d",&t); 120 for(int i=1;i<=t;i++){ 121 int x,y; 122 scanf("%d%d",&x,&y); 123 int c=lca(x,y); 124 node A=work(x,c); 125 node B=work(y,c); 126 if(A.b==-1||B.b==-1){ 127 ans[i]=-1; 128 continue; 129 } 130 if(x==c||y==c){ 131 ans[i]=A.b+B.b+1; 132 continue; 133 } 134 ans[i]=A.b+B.b+2; 135 x=A.a; 136 y=B.a; 137 if(id[x]>id[y])swap(x,y); 138 q[id[x]-1].push_back((node){y,-i}); 139 q[id[x]+size[x]-1].push_back((node){y,i}); 140 } 141 for(int i=1;i<=n;i++){ 142 for(int j=0;j<road[i].size();j++)update(road[i][j]); 143 for(int j=0;j<q[i].size();j++){ 144 int num=(q[i][j].b>0?1:-1); 145 int x=q[i][j].a;int y=q[i][j].b*num; 146 sum[y]+=num*(check(id[x]+size[x]-1)-check(id[x]-1)); 147 } 148 } 149 for(int i=1;i<=t;i++){ 150 printf("%d\n",ans[i]-(sum[i]>0)); 151 } 152 return 0; 153 }