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 }
View Code

 

posted @ 2018-07-30 17:41  Xu-daxia  阅读(778)  评论(0编辑  收藏  举报