解题: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
原文地址:https://www.cnblogs.com/ydnhaha/p/10405060.html