码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2018-11-25 20:17:53      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:cst   std   输出   using   ring   void   双向   size   lca   

题意:

  $n$个城市,从$1$到$n$标号,$n$个城市构成一棵树。

  有$m$条双向公交路线,对于每条路线,公交沿着两个终点站之间的最短路径行驶并会在沿途各站停车。从一个城市只能坐公交前往其他城市。

  有$q$个询问:从一个城市到另一个城市要搭乘多少趟公交?不能到达输出$-1$。


 

对于每个询问$x,y$,求出$z=lca(x,y)$。

先从$x$和$y$出发到达$z$下方的城市$x‘$和$y‘$使得再坐一趟车可到$z$,记步数和为$s$。倍增,预处理$f[i][j]$表示从$i$出发坐$2^{j}$趟车最上能到达的位置。

若$x‘$可坐车到$y‘$则答案为$s+1$,否则答案为$s+2$。

考虑dfs过程中用树状数组按dfs序维护,若$x‘$的子树中终点站在$y‘$子树内的车,那么可以坐一趟车到达。预处理时把公交和询问分别挂在对应端点上。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <vector>
  5 using namespace std;
  6 const int N=200010,K=19;
  7 struct ask {
  8     int y,id,s;
  9     ask () {}
 10     ask (int y,int id,int s):y(y),id(id),s(s) {}
 11 };
 12 int n,m,q,x,y,z,f[N][K],ans[N],c[N],sum[N];
 13 int cnt,dfn[N],fa[N],son[N],top[N],dep[N],size[N];
 14 int p,head[N],to[N],nxt[N];
 15 vector<int> h[N];
 16 vector<ask> A[N];
 17 inline int read() {
 18     int re=0; char ch=getchar();
 19     while (ch<0||ch>9) ch=getchar();
 20     while (ch>=0&&ch<=9) re=re*10+ch-48,ch=getchar();
 21     return re;
 22 }
 23 inline void add(int x,int y) {
 24     to[++p]=y; nxt[p]=head[x]; head[x]=p;
 25 }
 26 void tree_add(int x) {for (; x<=n; x+=(x&-x)) ++c[x];}
 27 int tree_sum(int x) {int re=0; for (; x; x-=(x&-x)) re+=c[x]; return re;}
 28 void dfs1(int x) {
 29     size[x]=1; dfn[x]=++cnt;
 30     for (int i=head[x]; i; i=nxt[i]) {
 31         dep[to[i]]=dep[x]+1;
 32         dfs1(to[i]);
 33         size[x]+=size[to[i]];
 34         if (size[to[i]]>size[son[x]]) son[x]=to[i];
 35     }
 36 }
 37 void dfs2(int x,int tp) {
 38     top[x]=tp;
 39     if (son[x]) dfs2(son[x],tp);
 40     for (int i=head[x]; i; i=nxt[i]) {
 41         if (to[i]==son[x]) continue;
 42         dfs2(to[i],to[i]);
 43     }
 44 }
 45 void dfs3(int x) {
 46     for (int i=head[x]; i; i=nxt[i]) {
 47         dfs3(to[i]);
 48         if (dep[f[to[i]][0]]<dep[f[x][0]]) f[x][0]=f[to[i]][0];
 49     }
 50 }
 51 void dfs4(int x) {
 52     for (int i=0; i<A[x].size(); i++) {
 53         A[x][i].s=tree_sum(dfn[A[x][i].y]+size[A[x][i].y]-1)-tree_sum(dfn[A[x][i].y]-1);
 54     }
 55     for (int i=0; i<h[x].size(); i++) tree_add(dfn[h[x][i]]);
 56     int tmp;
 57     for (int i=head[x]; i; i=nxt[i]) dfs4(to[i]);
 58     for (int i=0; i<A[x].size(); i++) {
 59         tmp=tree_sum(dfn[A[x][i].y]+size[A[x][i].y]-1)-tree_sum(dfn[A[x][i].y]-1);
 60         if (tmp==A[x][i].s) ans[A[x][i].id]++;
 61     }
 62 }
 63 int lca(int a,int b) {
 64     while (top[a]!=top[b]) {
 65         if (dep[top[a]]>dep[top[b]]) swap(a,b);
 66         b=fa[top[b]];
 67     }
 68     if (dep[a]>dep[b]) swap(a,b);
 69     return a;
 70 }
 71 int main() {
 72     n=read();
 73     for (int i=2; i<=n; i++) add(fa[i]=read(),i);
 74     dfs1(1); dfs2(1,1);
 75     m=read();
 76     for (int i=1; i<=n; i++) f[i][0]=i;
 77     for (int i=1; i<=m; i++) {
 78         x=read(); y=read();
 79         h[x].push_back(y); h[y].push_back(x);
 80         z=lca(x,y);
 81         if (dep[z]<dep[f[x][0]]) f[x][0]=z;
 82         if (dep[z]<dep[f[y][0]]) f[y][0]=z;
 83     }
 84     dfs3(1);
 85     for (int j=1; j<K; j++) 
 86         for (int i=1; i<=n; i++)
 87             f[i][j]=f[f[i][j-1]][j-1];
 88     q=read();
 89     for (int i=1; i<=q; i++) {
 90         x=read(); y=read(); z=lca(x,y);
 91         if (x==y) continue;
 92         if (f[x][K-1]!=f[y][K-1]) {ans[i]=-1; continue;}
 93         for (int j=K-1; j>=0; j--) {
 94             if (dep[f[x][j]]>dep[z]) ans[i]+=(1<<j),x=f[x][j];
 95             if (dep[f[y][j]]>dep[z]) ans[i]+=(1<<j),y=f[y][j];
 96         }
 97         ans[i]++;
 98         if (z!=x && z!=y) A[x].push_back(ask(y,i,0));
 99     }
100     dfs4(1);
101     for (int i=1; i<=q; i++) printf("%d\n",ans[i]);
102     return 0;
103 }

 

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

标签:cst   std   输出   using   ring   void   双向   size   lca   

原文地址:https://www.cnblogs.com/hnooo/p/10016132.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!