• [HNOI2016]树


    Description

      小A想做一棵很大的树,但是他手上的材料有限,只好用点小技巧了。开始,小A只有一棵结点数为N的树,结
    点的编号为1,2,…,N,其中结点1为根;我们称这颗树为模板树。小A决定通过这棵模板树来构建一颗大树。构建过
    程如下:(1)将模板树复制为初始的大树。(2)以下(2.1)(2.2)(2.3)步循环执行M次(2.1)选择两个数字a,b,
    其中1<=a<=N,1<=b<=当前大树的结点数。(2.2)将模板树中以结点a为根的子树复制一遍,挂到大树中结点b的下
    方(也就是说,模板树中的结点a为根的子树复制到大树中后,将成为大树中结点b的子树)。(2.3)将新加入大树
    的结点按照在模板树中编号的顺序重新编号。例如,假设在进行2.2步之前大树有L个结点,模板树中以a为根的子
    树共有C个结点,那么新加入模板树的C个结点在大树中的编号将是L+1,L+2,…,L+C;大树中这C个结点编号的大小
    顺序和模板树中对应的C个结点的大小顺序是一致的。下面给出一个实例。假设模板树如下图:


    根据第(1)步,初始的大树与模板树是相同的。在(2.1)步,假设选择了a=4,b=3。运行(2.2)和(2.3)后,得到新的
    大树如下图所示

    现在他想问你,树中一些结点对的距离是多少。

    Input

      第一行三个整数:N,M,Q,以空格隔开,N表示模板树结点数,M表示第(2)中的循环操作的次数,Q 表示询问数
    量。接下来N-1行,每行两个整数 fr,to,表示模板树中的一条树边。再接下来M行,每行两个整数x,to,表示将模
    板树中 x 为根的子树复制到大树中成为结点to的子树的一次操作。再接下来Q行,每行两个整数fr,to,表示询问
    大树中结点 fr和 to之间的距离是多少。N,M,Q<=100000

    Output

      输出Q行,每行一个整数,第 i行是第 i个询问的答案。

    Sample Input

    5 2 3
    1 4
    1 3
    4 2
    4 5
    4 3
    3 2
    6 9
    1 8
    5 3

    Sample Output

    6
    3
    3

    HINT

    经过两次操作后,大树变成了下图所示的形状:



    结点6到9之间经过了6条边,所以距离为6;类似地,结点1到8之间经过了3条边;结点5到3之间也经过了3条边。

    如果看不懂可以看一下下面几个博客

    http://www.cnblogs.com/wfj2048/p/6416591.html

    把每一个新添的子树缩成一个点,那么新树就只有m+1点(模板树算一个点)

    每一次加树就等于链接新树中两个点

    判断y在哪个点用二分,链接的边权为两个点代表的子树根节点的距离

    判断这个新点连上的点对应模板树的哪个点,需要判断dfs序区间内的区间第k大,这要用到主席树

    查询(x,y)时分清况:先求出(x,y)在模板树的对应点(u,v),新树上的w=LCA(p,q)

    1.两个属同一个子树,在模板树求(u,v)距离

    2.不属于同一子树(p,q),先求出在新树上的距离,再加上u->u的子树根的距离(模板树),v同理

    因为这样算出的距离在w的子树中可能多算,因为路径不一定经过w的根

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 typedef long long lol;
      8 struct ZYYS
      9 {
     10   lol rt,id,pre;
     11   lol l,r;
     12 }a[100005];
     13 lol pos,ch[6000005][2],sum[6000005],n,m,root[100005];
     14 lol ans;
     15 struct Tree
     16 {
     17   struct Node
     18   {
     19     lol next,to;
     20     lol dis;
     21   }edge[200005];
     22   lol head[100005],num,dep[100005],size[100005],id[100005],lx[100005],rx[100005],top[100005],cnt,son[100005],fa[100005];
     23   lol d[100005];
     24   void add(lol u,lol v,lol dis)
     25   {
     26     num++;
     27     edge[num].next=head[u];
     28     head[u]=num;
     29     edge[num].to=v;
     30     edge[num].dis=dis;
     31   }
     32   void dfs1(lol x,lol pa)
     33   {lol i;
     34     dep[x]=dep[pa]+1;
     35     size[x]=1;
     36     fa[x]=pa;
     37     for (i=head[x];i;i=edge[i].next)
     38       {
     39     lol v=edge[i].to;
     40     if (v!=pa)
     41       {
     42         d[v]=d[x]+edge[i].dis;
     43         dfs1(v,x);
     44         size[x]+=size[v];
     45         if (size[v]>size[son[x]]) son[x]=v;
     46       }
     47       }
     48   }
     49   void dfs2(lol x,lol pa,lol tp)
     50   {lol i;
     51     lx[x]=++cnt;
     52     id[cnt]=x;
     53     top[x]=tp;
     54     if (son[x])
     55       {
     56     dfs2(son[x],x,tp);
     57       }
     58     for (i=head[x];i;i=edge[i].next)
     59       {
     60     lol v=edge[i].to;
     61     if (v==pa||v==son[x]) continue;
     62     dfs2(v,x,v);
     63       }
     64     rx[x]=cnt;
     65   }
     66   lol gettop(lol x,lol y)
     67   {lol z;
     68     while (top[x]!=top[y])
     69       {
     70     z=top[x];
     71     x=fa[top[x]];
     72       }
     73     if (x==y) return z;
     74     return son[y];
     75   }
     76   lol lca(lol x,lol y)
     77   {
     78     while (top[x]!=top[y])
     79       {
     80     if (dep[top[x]]<dep[top[y]]) swap(x,y);
     81     x=fa[top[x]];
     82       }
     83     if (dep[x]>dep[y]) swap(x,y);
     84     return x;
     85   }
     86   lol dist(lol x,lol y)
     87   {
     88     return d[x]+d[y]-2*d[lca(x,y)];
     89   }
     90 }t1,t2;
     91 lol getid(lol k,lol r)
     92 {
     93   lol l=1,as=0;
     94   while (l<=r)
     95     {
     96       lol mid=(l+r)/2;
     97       if (a[mid].l<=k) as=mid,l=mid+1;
     98       else r=mid-1;
     99     }
    100   return as;
    101 }
    102 void update(lol x,lol &y,lol l,lol r,lol k)
    103 {
    104   y=++pos;
    105   ch[y][0]=ch[x][0];ch[y][1]=ch[x][1];
    106   sum[y]=sum[x]+1;
    107   if (l==r) return;
    108   lol mid=(l+r)/2;
    109   if (k<=mid) update(ch[x][0],ch[y][0],l,mid,k);
    110   else update(ch[x][1],ch[y][1],mid+1,r,k);
    111 }
    112 lol query(lol x,lol y,lol l,lol r,lol k)
    113 {
    114   if (l==r) return l;
    115   lol mid=(l+r)/2;
    116   lol zyys=sum[ch[y][0]]-sum[ch[x][0]];
    117   if (zyys<k) return query(ch[x][1],ch[y][1],mid+1,r,k-zyys);
    118   else return query(ch[x][0],ch[y][0],l,mid,k);
    119 }
    120 int main()
    121 {lol i,Q;
    122   lol x,y,u,v;
    123   cin>>n>>m>>Q;
    124   for (i=1;i<=n-1;i++)
    125     {
    126       scanf("%lld%lld",&u,&v);
    127       t1.add(u,v,1);
    128       t1.add(v,u,1);
    129     }
    130   t1.dfs1(1,0);
    131   t1.dfs2(1,0,1);
    132   for (i=1;i<=n;i++)
    133     update(root[i-1],root[i],1,n,t1.id[i]);
    134   a[1].id=1;a[1].rt=1;a[1].l=1;a[1].r=n;
    135   for (i=1;i<=m;i++)
    136     {
    137       scanf("%lld%lld",&x,&y);
    138       a[i+1].id=i+1;a[i+1].rt=x;
    139       a[i+1].l=a[i].r+1;
    140       a[i+1].r=a[i+1].l+t1.size[x]-1;
    141       lol z=getid(y,i);
    142       a[i+1].pre=y=query(root[t1.lx[a[z].rt]-1],root[t1.rx[a[z].rt]],1,n,y-a[z].l+1);
    143       t2.add(z,i+1,t1.d[y]-t1.d[a[z].rt]+1);
    144       t2.add(i+1,z,t1.d[y]-t1.d[a[z].rt]+1);
    145     }
    146   t2.dfs1(1,0);t2.dfs2(1,0,1);
    147   for (i=1;i<=Q;i++)
    148     {
    149       scanf("%lld%lld",&x,&y);
    150       lol p=getid(x,m+1),q=getid(y,m+1);
    151       lol w=t2.lca(p,q);
    152       lol u=query(root[t1.lx[a[p].rt]-1],root[t1.rx[a[p].rt]],1,n,x-a[p].l+1);
    153       lol v=query(root[t1.lx[a[q].rt]-1],root[t1.rx[a[q].rt]],1,n,y-a[q].l+1);
    154       if (p==q)
    155     {
    156       printf("%lld
    ",t1.dist(u,v));
    157     }
    158       else
    159     {
    160       if (p==w) swap(p,q),swap(u,v);
    161       if (q==w)
    162         {
    163           x=t2.gettop(p,w);
    164           ans=t2.d[p]-t2.d[x]+t1.d[u]-t1.d[a[p].rt];
    165           u=a[x].pre;
    166           ans+=t1.dist(u,v)+1;
    167         }
    168       else
    169         {
    170           ans=(t1.d[u]-t1.d[a[p].rt]+t1.d[v]-t1.d[a[q].rt]);
    171           ans+=t2.dist(p,q);
    172           x=t2.gettop(p,w);y=t2.gettop(q,w);
    173           u=a[x].pre;v=a[y].pre;
    174           ans+=(t1.d[a[w].rt]-t1.d[t1.lca(u,v)])*2;
    175         }
    176       printf("%lld
    ",ans);
    177     }
    178     }
    179 }
  • 相关阅读:
    数据转换类型和算数运算符
    语言基础+数据类型
    JS(一)Prototype的使用
    Jquery EasyUI简介和数据的增删改查
    http简介
    《JavaScript语言精粹》笔记
    wcf
    简单工厂模式与抽象工厂模式
    <转载>C#中的特性(Attributes)
    <转载>C#IEnumerable和IEnumerator 详解
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8260901.html
Copyright © 2020-2023  润新知