• Lowest Common Ancestor


    题意:求 $f(i) = sum_{j=1}^{i-1}{w(LCA(i,j))}$,输出所有的$f(i)$

    解法:

    首先,如果题目变为有K个关键点,问$f(i) = sum_{p∈{K}} {w(LCA(i,K))}$做法显然,只要dfs一遍即可。

    考虑cdq分治,每一次对于区间[L,R],将[L,R]的点建虚树,而后对其dfs,求[L,mid]的关键点对[mid+1,R]的答案的贡献

    注意用RMQ_LCA,O(1),不然会TLE。

      1 #include <iostream>
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 
      7 #define N 200010
      8 #define p E[i].x
      9 #define LL long long
     10 
     11 using namespace std;
     12 
     13 struct edge
     14 {
     15     int x,to;
     16 }E[N];
     17 
     18 int n,totE,tot2;
     19 int g[N],dfsn[N],w[N],d[N],L[N],fa[N];
     20 int dfsn2[N<<1],mind[N<<1][20],maxt[N<<1];
     21 LL ansv[N];
     22 
     23 void addedge(int x,int y)
     24 {
     25     E[++totE]=(edge){y,g[x]}; g[x]=totE;
     26 }
     27 
     28 void dfs(int x)
     29 {
     30     dfsn[x]=++dfsn[0];
     31     for(int i=g[x];i;i=E[i].to)
     32     {
     33         d[p]=d[x]+1;
     34         dfs(p);
     35     }
     36 }
     37 
     38 void dfs2(int x)
     39 {
     40     dfsn2[++tot2]=x;
     41     mind[tot2][0]=x;
     42     L[x]=tot2;
     43     for(int i=g[x];i;i=E[i].to)
     44     {
     45         dfs2(p);
     46         dfsn2[++tot2]=x;
     47         mind[tot2][0]=x;
     48     }
     49 }
     50 
     51 inline int LCA(int x,int y)
     52 {
     53     int l=L[x],r=L[y];
     54     if(x==y) return x;
     55     if(l>r) swap(l,r);
     56     int t=maxt[r-l+1];
     57     x = mind[l][t];
     58     y = mind[r-(1<<t)+1][t];
     59     if(d[x]<d[y]) return x;
     60     else return y;
     61 }
     62 
     63 namespace virtual_tree
     64 {
     65     edge E[N];
     66     
     67     int tot,totE,ed;
     68     int g[N],tmp[N],id[N],num[N],q[N],siz[N];
     69     
     70     void addedge(int x,int y)
     71     {
     72         if(!id[x])
     73         {
     74             id[x]=++tot;
     75             num[tot]=x;
     76         }
     77         if(!id[y])
     78         {
     79             id[y]=++tot;
     80             num[tot]=y;
     81         }
     82         x=id[x];
     83         y=id[y];
     84         E[++totE]=(edge){y,g[x]};
     85         g[x]=totE;
     86     }
     87     
     88     bool cmp(int a,int b)
     89     {
     90         return dfsn[a]<dfsn[b];
     91     }
     92     
     93     void dfs(int x)
     94     {
     95         for(int i=g[x];i;i=E[i].to)
     96         {
     97             dfs(p);
     98             siz[x]+=siz[p];
     99         }
    100     }
    101     
    102     void build_tree()
    103     {
    104         for(int t=1;t<=tmp[0];t++)
    105         {
    106             int i=tmp[t];
    107             int lca=LCA(i,q[ed]);
    108             if(lca==q[ed]) q[++ed]=i;
    109             else
    110             {
    111                 while(ed>1 && dfsn[q[ed-1]]>dfsn[lca])
    112                     addedge(q[ed-1],q[ed]), ed--;
    113                 if(dfsn[q[ed]]>dfsn[lca])
    114                     addedge(lca,q[ed]), ed--;
    115                 if(dfsn[q[ed]]<dfsn[lca]) q[++ed]=lca;
    116                 q[++ed]=i;
    117             }
    118         }
    119         while(ed>1)
    120             addedge(q[ed-1],q[ed]), ed--;
    121     }
    122     
    123     void dfs2(int x,int mid,int r,LL now)
    124     {
    125         if(num[x]<=r && num[x]>mid) ansv[num[x]] += now + siz[x]*(LL)w[num[x]];
    126         for(int i=g[x];i;i=E[i].to)
    127             dfs2(p,mid,r,now + (siz[x]-siz[p])*(LL)w[num[x]]);
    128     }
    129     
    130     void solve(int l,int r,int mid)
    131     {
    132         totE=0;
    133         for(int i=1;i<=tot;i++)
    134         {
    135             id[num[i]]=0;
    136             g[i]=0;
    137             num[i]=0;
    138             siz[i]=0;
    139         }
    140         tot=1;
    141         num[tot]=id[1]=1;
    142         q[ed=1]=1;
    143         tmp[0]=0;
    144         for(int i=l;i<=r;i++)
    145         {
    146             if(i!=1)
    147             {
    148                 num[++tot]=i;
    149                 id[i]=tot;
    150                 tmp[++tmp[0]]=i;
    151             }
    152             if(i<=mid) siz[id[i]]=1;
    153         }
    154         sort(tmp+1,tmp+tmp[0]+1,cmp);
    155         build_tree();
    156         dfs(1);
    157         dfs2(1,mid,r,0LL);
    158     }
    159 };
    160 
    161 void cdq(int l,int r)
    162 {
    163     if(l==r) return;
    164     int mid=(l+r)>>1;
    165     cdq(l,mid);
    166     cdq(mid+1,r);
    167     virtual_tree::solve(l,r,mid);
    168 }
    169 
    170 int main()
    171 {
    172 //    freopen("test.txt","r",stdin);
    173     while(~scanf("%d",&n))
    174     {
    175         for(int i=1;i<=n;i++) g[i]=0;
    176         totE=0;
    177         for(int i=1;i<=n;i++) scanf("%d",&w[i]);
    178         for(int i=2;i<=n;i++)
    179         {
    180             scanf("%d",&fa[i]);
    181             addedge(fa[i],i);
    182         }
    183         dfsn[0]=0;
    184         tot2=0;
    185         d[1]=1;
    186         dfs(1);
    187         dfs2(1);
    188         int j=0;
    189         for(int i=1;i<=tot2;i++)
    190         {
    191             maxt[i]=j;
    192             if(i==(1<<(j+1))) j++;
    193         }
    194         for(int t=1;t<20;t++)
    195             for(int i=1;i+(1<<t)-1<=tot2;i++)
    196             {
    197                 int x=mind[i][t-1];
    198                 int y=mind[i+(1<<(t-1))][t-1];
    199                 if(d[x]<d[y]) mind[i][t]=x;
    200                 else mind[i][t]=y;
    201             }
    202         for(int i=1;i<=n;i++) ansv[i]=0;
    203         cdq(1,n);
    204         for(int i=2;i<=n;i++) printf("%lld
    ",ansv[i]);
    205     }
    206     return 0;
    207 }
    View Code
  • 相关阅读:
    019_linuxC++之_函数模板引入
    018_linuxC++之_抽象类的引入
    017_linuxC++之_多态的引入
    《将博客搬至CSDN》
    016_linuxC++之_多重继承
    013_linuxC++之_派生类中权限的调整
    015_linuxC++之_覆写
    014_linuxC++之_不同类型的继承
    012_linuxC++之_类的继承定义
    011_linuxC++之_继承的引入
  • 原文地址:https://www.cnblogs.com/lawyer/p/6443605.html
Copyright © 2020-2023  润新知