zoukankan      html  css  js  c++  java
  • 「BZOJ3572」[HNOI2014]世界树

    建出虚树

    两遍dp求出虚树上的各点被哪个点管辖

    再对虚树上的每一条边计算贡献

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int N=300010,P=25,oo=2e9;
      4 int n,m,q,a[N];
      5 int fa[N][P],dep[N],id[N],siz[N],dfn;
      6 int ans[N],b[N],c[N],f[N],d[N],w[N];
      7 struct Edge{
      8     int from,to,v,next;
      9     Edge(int _from=0,int _to=0,int _v=0,int _next=0):from(_from),to(_to),v(_v),next(_next){}
     10 }edge[N<<1];
     11 int edge_tot,last[N];
     12 inline void add_edge(int f,int t,int vv){edge[++edge_tot]=Edge(f,t,vv,last[f]),last[f]=edge_tot;return;}
     13 int cmp(int x,int y){return id[x]<id[y];}
     14 void dfs(int k,int father,int d){
     15     fa[k][0]=father,dep[k]=d,id[k]=++dfn,siz[k]=1;
     16     for(int i=last[k];i;i=edge[i].next){
     17         if(edge[i].to==father) continue;
     18         dfs(edge[i].to,k,d+1);
     19         siz[k]+=siz[edge[i].to];
     20     }
     21     return;
     22 }
     23 int getlca(int x,int y){
     24     if(dep[x]<dep[y]) swap(x,y);
     25     for(int i=19;i>=0;i--) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
     26     if(x==y) return x;
     27     for(int i=19;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
     28     return fa[x][0];
     29 }
     30 inline int getson(int x,int y){
     31     for(int i=19;i>=0;i--) if(dep[fa[y][i]]>dep[x]) y=fa[y][i];
     32     return y;
     33 }
     34 int sta[N],top;
     35 inline void build(){
     36     int lca;
     37     if(f[1]!=1) sta[top++]=1;
     38     for(int i=1;i<=m;i++){
     39         while(1){
     40             if(!top) break;
     41             lca=getlca(sta[top-1],a[i]);
     42             if(lca==sta[top-1]) break;
     43             else{
     44                 top--;
     45                 if(id[sta[top-1]]>=id[lca]){
     46                     add_edge(sta[top-1],sta[top],siz[getson(sta[top-1],sta[top])]-siz[sta[top]]);
     47                 }else{
     48                     add_edge(lca,sta[top],siz[getson(lca,sta[top])]-siz[sta[top]]);
     49                     sta[top++]=lca;
     50                     break;
     51                 }
     52             }
     53         }
     54         sta[top++]=a[i];
     55     }
     56     while(top>=2){top--;add_edge(sta[top-1],sta[top],siz[getson(sta[top-1],sta[top])]-siz[sta[top]]);}
     57     return;
     58 }
     59 void dfs_dp1(int k,int father){
     60     c[++dfn]=k,w[k]=siz[k];
     61     for(int i=last[k];i;i=edge[i].next){
     62         if(edge[i].to==father) continue;
     63         w[k]-=siz[edge[i].to]+edge[i].v;
     64         dfs_dp1(edge[i].to,k);
     65         if(d[k]>d[edge[i].to]+dep[edge[i].to]-dep[k]) d[k]=d[edge[i].to]+dep[edge[i].to]-dep[k],f[k]=f[edge[i].to];
     66         else if(d[k]==d[edge[i].to]+dep[edge[i].to]-dep[k]&&f[edge[i].to]<f[k]) f[k]=f[edge[i].to];
     67     }
     68     return;
     69 }
     70 void dfs_dp2(int k,int father){
     71     for(int i=last[k];i;i=edge[i].next){
     72         if(edge[i].to==father) continue;
     73         if(d[edge[i].to]>d[k]+dep[edge[i].to]-dep[k]) d[edge[i].to]=d[k]+dep[edge[i].to]-dep[k],f[edge[i].to]=f[k];
     74         else if(d[edge[i].to]==d[k]+dep[edge[i].to]-dep[k]&&f[edge[i].to]>f[k]) f[edge[i].to]=f[k];
     75         dfs_dp2(edge[i].to,k);
     76     }
     77     return;
     78 }
     79 inline void solve(int k){
     80     int t1=edge[k].from,t2=edge[k].to,nxt;
     81     if(f[t1]==f[t2]){ans[f[t1]]+=edge[k].v;return;}
     82     int mid=t2;
     83     for(int i=19;i>=0;i--){
     84         nxt=fa[mid][i];
     85         if(id[nxt]<id[t1]) continue;
     86         if(d[t1]+dep[nxt]-dep[t1]>d[t2]+dep[t2]-dep[nxt]||(d[t1]+dep[nxt]-dep[t1]==d[t2]+dep[t2]-dep[nxt])&&f[t2]<f[t1]) mid=nxt;
     87     }
     88     ans[f[t1]]+=siz[getson(t1,mid)]-siz[mid];
     89     ans[f[t2]]+=siz[mid]-siz[t2];
     90     return;
     91 }
     92 inline void clear(){
     93     for(int i=1;i<=dfn;i++) last[c[i]]=f[c[i]]=ans[c[i]]=w[c[i]]=0,d[c[i]]=oo;
     94     edge_tot=dfn=top=0;
     95     return;
     96 }
     97 void query(){
     98     int t1,t2;
     99     scanf("%d",&m);
    100     for(int i=1;i<=m;i++) scanf("%d",&a[i]),b[i]=a[i],f[a[i]]=a[i],d[a[i]]=0;
    101     sort(a+1,a+m+1,cmp);
    102     build();
    103     dfs_dp1(1,0);dfs_dp2(1,0);
    104     for(int i=1;i<=dfn;i++) ans[f[c[i]]]+=w[c[i]];
    105     for(int i=1;i<=edge_tot;i++)
    106         solve(i);
    107     for(int i=1;i<=m;i++) printf("%d ",ans[b[i]]);
    108     printf("
    ");
    109     clear();
    110     return;
    111 }
    112 int main(){
    113     int t1,t2;
    114     scanf("%d",&n);
    115     for(int i=1;i<n;i++){
    116         scanf("%d%d",&t1,&t2);
    117         add_edge(t1,t2,0);add_edge(t2,t1,0);
    118     }
    119     dfs(1,0,1);
    120     for(int i=1;i<=19;i++)
    121         for(int j=1;j<=n;j++)
    122             fa[j][i]=fa[fa[j][i-1]][i-1];
    123     memset(last,0,sizeof(last));memset(d,127/2,sizeof(d));
    124     edge_tot=dfn=0;
    125     scanf("%d",&q);
    126     while(q--) query();
    127     return 0;
    128 }
  • 相关阅读:
    python生成随机密码
    python计算md5值
    python---连接MySQL第五页
    python---连接MySQL第四页
    梯度下降(Gradient Descent)小结
    矩阵的线性代数意义
    矩阵的意义
    偏导数与全导数的关系 以及 偏微分与全微分的关系
    mysql-blog
    python及numpy,pandas易混淆的点
  • 原文地址:https://www.cnblogs.com/mycups/p/8527895.html
Copyright © 2011-2022 走看看