zoukankan      html  css  js  c++  java
  • 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
    ",ans[i]-(sum[i]>0));
    151     }
    152     return 0;
    153 }
    View Code
  • 相关阅读:
    POJ-1035 Spell checker---字符串处理
    hdu-3572 Task Schedule---最大流判断满流+dinic算法
    BZOJ4826: [Hnoi2017]影魔
    BZOJ4825: [Hnoi2017]单旋
    BZOJ3504: [Cqoi2014]危桥
    BZOJ4407: 于神之怒加强版
    BZOJ2818: Gcd
    BZOJ4542: [Hnoi2016]大数
    BZOJ4540: [Hnoi2016]序列
    BZOJ4537: [Hnoi2016]最小公倍数
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9391830.html
Copyright © 2011-2022 走看看