zoukankan      html  css  js  c++  java
  • 解题:HNOI 2014 世界树

    题面

    首先建虚树

    DFS求虚树上每个点所属的点和到它所属点的距离,然后在=考虑虚树所有的边(对应原树一条链)。如果两个端点所属节点不同就倍增出分界点统计答案,否则不用管(之后会统计到的);注意根节点特殊讨论。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 const int N=600005,K=20,inf=1e9;
      6 int T,n,m,t1,t2,cnt,tot,top;
      7 int p[N],noww[N],goal[N];
      8 int siz[N],dep[N],dfn[N],upt[N][K],oth[N][K];
      9 int a[N],b[N],c[N],d[N],bel[N],stk[N],ans[N];
     10 bool cmp(int a,int b)
     11 {
     12     return dfn[a]<dfn[b];
     13 }
     14 void Link(int f,int t)
     15 {
     16     noww[++cnt]=p[f];
     17     goal[cnt]=t,p[f]=cnt;
     18 }
     19 void DFS(int nde,int fth,int dth)
     20 {
     21     siz[nde]=1,dep[nde]=dth;
     22     upt[nde][0]=fth,dfn[nde]=++tot;
     23     for(int i=1;i<=19&&upt[nde][i-1];i++)
     24         upt[nde][i]=upt[upt[nde][i-1]][i-1];
     25     for(int i=p[nde];i;i=noww[i])
     26         if(goal[i]!=fth)
     27             DFS(goal[i],nde,dth+1),siz[nde]+=siz[goal[i]];
     28 }
     29 void Calc(int nde,int fth)
     30 {
     31     oth[nde][0]=siz[fth]-siz[nde];
     32     for(int i=1;i<=19&&upt[nde][i-1];i++)
     33         oth[nde][i]=oth[nde][i-1]+oth[upt[nde][i-1]][i-1];
     34     for(int i=p[nde];i;i=noww[i])
     35         if(goal[i]!=fth) Calc(goal[i],nde);
     36 }
     37 int LCA(int x,int y)
     38 {
     39     if(dep[x]<dep[y]) swap(x,y); 
     40     for(int i=19;dep[x]!=dep[y];i--)
     41         if(dep[upt[x][i]]>=dep[y]) x=upt[x][i];
     42     if(x==y) return x;
     43     for(int i=19;~i;i--)
     44         if(upt[x][i]!=upt[y][i]) 
     45             x=upt[x][i],y=upt[y][i];
     46     return upt[x][0];
     47 }
     48 int Dis(int x,int y)
     49 {
     50     int lca=LCA(x,y);
     51     return dep[x]+dep[y]-2*dep[lca];
     52 }
     53 bool Check(int a,int b,int d)
     54 {
     55     return c[a]+d<c[b]||(c[a]+d==c[b]&&bel[a]<bel[b]);
     56 }
     57 void Insert(int nde)
     58 {
     59     if(!top) stk[++top]=nde;
     60     else
     61     {
     62         int lca=LCA(nde,stk[top]); 
     63         if(lca!=stk[top]) 
     64         {
     65             while(top>1&&dfn[lca]<=dfn[stk[top-1]])    
     66                 Link(stk[top-1],stk[top]),top--;
     67             if(dfn[lca]<dfn[stk[top]])
     68                 Link(lca,stk[top]),top--;
     69             if(lca!=stk[top])        
     70                 stk[++top]=lca;
     71         }
     72         stk[++top]=nde;
     73     }
     74 }
     75 int Upt(int nde,int gal)
     76 {
     77     int ret=0;
     78     for(int i=19;~i;i--)
     79         if(gal&(1<<i))
     80             ret+=oth[nde][i],nde=upt[nde][i];
     81     return ret;
     82 }
     83 void DFS1(int nde)
     84 {
     85     if(!bel[nde]) c[nde]=inf;
     86     for(int i=p[nde];i;i=noww[i])
     87     {
     88         int g=goal[i],dd=dep[g]-dep[nde]; DFS1(g); 
     89         if(Check(g,nde,dd)) c[nde]=c[g]+dd,bel[nde]=bel[g];
     90     }
     91 }
     92 void DFS2(int nde,int lst)
     93 {
     94     int dd=dep[nde]-dep[lst];
     95     if(lst&&Check(lst,nde,dd))
     96         c[nde]=c[lst]+dd,bel[nde]=bel[lst];
     97     for(int i=p[nde];i;i=noww[i])
     98         DFS2(goal[i],nde),d[nde]+=d[goal[i]];
     99     if(!lst) ans[bel[nde]]+=n-d[nde];
    100     else if(bel[nde]!=bel[lst])
    101     {
    102         int cut=c[nde]+c[lst]+dd,chk=cut%2||bel[nde]<bel[lst],tmp;
    103         tmp=Upt(nde,cut/2-c[nde]-(chk^1)); 
    104         ans[bel[nde]]+=siz[nde]-d[nde]+tmp,d[nde]=siz[nde]+tmp;
    105     }
    106 }
    107 void Clear(int nde)
    108 {
    109     for(int i=p[nde];i;i=noww[i])
    110         Clear(goal[i]);
    111     bel[nde]=p[nde]=c[nde]=d[nde]=0;
    112 }
    113 int main()
    114 {
    115     scanf("%d",&n);
    116     for(int i=1;i<n;i++)
    117         scanf("%d%d",&t1,&t2),Link(t1,t2),Link(t2,t1);
    118     DFS(1,0,1),Calc(1,0),memset(p,0,sizeof p);
    119     scanf("%d",&T);
    120     while(T--)
    121     {
    122         scanf("%d",&m),cnt=top=0;
    123         for(int i=1;i<=m;i++) scanf("%d",&a[i]),b[i]=a[i];
    124         sort(a+1,a+1+m,cmp);  stk[top=1]=a[1],bel[a[1]]=a[1]; 
    125         for(int i=2;i<=m;i++) Insert(a[i]),bel[a[i]]=a[i];
    126         while(top>1) Link(stk[top-1],stk[top]),top--;
    127         DFS1(stk[1]),DFS2(stk[1],0);
    128         for(int i=1;i<=m;i++)
    129             printf("%d ",ans[b[i]]),ans[b[i]]=0; 
    130         Clear(stk[1]),puts("");
    131     }
    132     return 0;
    133 }
    View Code
  • 相关阅读:
    邻居子系统 之 邻居项创建__neigh_create
    邻居子系统 之 邻居表的初始化neigh_table_init
    IP输出 之 分片ip_fragment、ip_do_fragment
    IP输出 之 ip_output、ip_finish_output、ip_finish_output2
    邻居子系统输出 之 neigh_output、neigh_hh_output
    IP输出 之 ip_local_out
    TCP->IP输出 之 ip_queue_xmit、ip_build_and_send_pkt、ip_send_unicast_reply
    TCP输出 之 tcp_transmit_skb
    TCP输出 之 tcp_write_xmit
    TCP层sendmsg系统调用的实现分析
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10405060.html
Copyright © 2011-2022 走看看