放波建虚树的模板。

      大概是用一个栈维护根节点到当前关键点的一条链,把其他深度大于lca的都弹出去。

      每次做完记得复原。

      还有sort的时候一定要加cmp!!!

      bzoj 3611

      

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #define N 1000005
  6 #define ll long long
  7 #define inf 0x3f3f3f3f
  8 using namespace std;
  9 inline int read()
 10 {
 11     int p=0;char c=getchar();
 12     while(c<'0'||c>'9')c=getchar();
 13     while(c>='0'&&c<='9')p=p*10+c-'0',c=getchar();
 14     return p;
 15 }
 16 int n;
 17 int dfn[N];
 18 int fa[N][21];
 19 int dep[N],z;
 20 int head[N],ver[N*2],nxt[N*2],tot;
 21 void add(int a,int b)
 22 {
 23     tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;
 24 }
 25 void dfs(int x,int f)
 26 {
 27     dfn[x]=++z;
 28     for(int i=head[x];i;i=nxt[i])
 29     {
 30         if(ver[i]==f)continue;
 31         dep[ver[i]]=dep[x]+1;
 32         fa[ver[i]][0]=x;
 33         dfs(ver[i],x);
 34     }
 35     return ;
 36 }
 37 void lca()
 38 {
 39     for(int i=1;i<=20;i++)
 40     {
 41         for(int j=1;j<=n;j++)
 42         {
 43             fa[j][i]=fa[fa[j][i-1]][i-1];
 44         }
 45     }return ;
 46 }
 47 int lca(int x,int y)
 48 {
 49     if(dep[x]<dep[y])swap(x,y);
 50     for(int i=20;i>=0;i--)if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
 51     if(x==y)return x;
 52     for(int i=20;i>=0;i--)
 53     {
 54         if(fa[x][i]!=fa[y][i])
 55         {
 56             x=fa[x][i];y=fa[y][i];
 57         }
 58     }
 59     return fa[x][0];
 60 }
 61 bool cmp(int x,int y)
 62 {
 63     return dfn[x]<dfn[y];
 64 }
 65 int now[N],cnt;
 66 int st[N],top;
 67 int dian[N],num;
 68 int vis[N];
 69 void build()
 70 {
 71     tot=0;
 72     st[1]=1;top=1;
 73     for(int i=1;i<=cnt;i++)
 74     {
 75         if(now[i]==1)continue;
 76         int v=now[i];
 77         int la=lca(st[top],v);
 78         if(st[top]!=la)
 79         {
 80             while(top>=2&&dep[st[top-1]]>dep[la])
 81             {
 82                 add(st[top-1],st[top]);top--;
 83             }
 84             add(la,st[top]);top--;
 85             if(st[top]!=la)st[++top]=la;
 86         }
 87         st[++top]=v;
 88     }
 89     while(top>=2)add(st[top-1],st[top]),top--;
 90 }
 91 ll ans1;
 92 int ans2,ans3;
 93 int size[N];
 94 int mx1[N],mx2[N],mn1[N],mn2[N];
 95 void dfs(int x)
 96 {
 97     dian[++num]=x;
 98     if(vis[x])size[x]=1;
 99     else size[x]=0;
100     mx1[x]=mx2[x]=0;
101     mn1[x]=mn2[x]=inf;
102     for(int i=head[x];i;i=nxt[i])
103     {
104         int quan=dep[ver[i]]-dep[x];
105         dfs(ver[i]);
106         if(vis[ver[i]])mn1[ver[i]]=0;
107         if(mn1[ver[i]]+quan<mn1[x])
108         {
109             mn2[x]=mn1[x];
110             mn1[x]=mn1[ver[i]]+quan;
111         }
112         else if(mn1[ver[i]]+quan<mn2[x])mn2[x]=mn1[ver[i]]+quan;
113         ans1+=(long long)size[ver[i]]*(cnt-size[ver[i]])*quan;
114         size[x]+=size[ver[i]];
115         if(mx1[ver[i]]+quan>mx1[x])
116         {
117             mx2[x]=mx1[x];
118             mx1[x]=mx1[ver[i]]+quan;
119         }
120         else if(mx1[ver[i]]+quan>mx2[x])mx2[x]=mx1[ver[i]]+quan;
121     }
122     if(vis[x])ans2=min(ans2,mn1[x]);
123     else ans2=min(ans2,mn1[x]+mn2[x]);
124     if(mx2[x])ans3=max(ans3,mx1[x]+mx2[x]);
125     else if(vis[x])ans3=max(ans3,mx1[x]);
126 }
127 int main()
128 {
129     n=read();
130     int t1,t2,t3,t4;
131     for(int i=1;i<n;i++)
132     {
133         t1=read();t2=read();
134         add(t1,t2);add(t2,t1);
135     }
136     dep[1]=1;
137     dfs(1,-1);
138     lca();
139     int q,k;
140     q=read();
141     memset(head,0,sizeof(head));
142     for(int i=1;i<=q;i++)
143     {
144         ans1=0;ans2=inf;ans3=0;
145         k=read();cnt=k;num=0;
146         for(int j=1;j<=k;j++)now[j]=read(),vis[now[j]]=1;
147         sort(now+1,now+k+1,cmp);
148         build();dfs(1);
149         for(int j=1;j<=cnt;j++)vis[now[j]]=0;
150         for(int j=1;j<=num;j++)head[dian[j]]=0;num=0;
151         printf("%lld %d %d\n",ans1,ans2,ans3);
152     }
153     return 0;
154 }
View Code

相关文章: