题目传送门
分析:
虚数模板练习,只是在这里放个码2333
对于每一个询问,我们构建只与这些点有关键联系的点的新的一棵树
由于关键点只有可能是这些点去它们的LCA
诶每加入一个点,最多只会加入一个LCA
所以空间是O(n)的,复杂度为O(logn)
我们首先先预处理出每个店的dfs入栈序号和出栈序号
首先先将读入的点加上根节点按入栈序排序
然后求出相邻两个点的LCA
思考一下(胡乱分析一下)我们知道这些点一定是所有关键点了
再按入栈序排一次序
考虑根节点到目前节点的树上关键点的路径,把它们加入一个栈中
我们考虑新加入点与前面的栈中的点连边
如果这个点的入栈序大于栈顶点的出栈序,那我们把栈顶pop掉
直到符合条件即加入点在栈顶点的子树中,然后连边
虚树就建好了。。
然后这道题很裸,大力DP就好了
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #define maxn 5000005 #define INF 0x3f3f3f3f using namespace std; inline long long getint() { long long num=0,flag=1;char c; while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1; while(c>='0'&&c<='9')num=num*10+c-48,c=getchar(); return num*flag; } int n,m,N; int fir[maxn],nxt[maxn],to[maxn],cnt; int fa[maxn],dpt[maxn],tp[maxn],sz[maxn],son[maxn]; int In[maxn],Out[maxn],cur,tot; long long h[maxn]; long long f[maxn],g[maxn]; int stk[maxn],top; int P[maxn]; vector<int>G[maxn]; long long ans1,ans2,ans3; inline bool cmp(int x,int y){return In[x]<In[y];} inline void newnode(int u,int v) {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;} inline void dfs1(int u) { sz[u]=1; for(int i=fir[u];i;i=nxt[i]) if(to[i]!=fa[u]) { dpt[to[i]]=dpt[u]+1,fa[to[i]]=u; dfs1(to[i]); sz[u]+=sz[to[i]];if(sz[to[i]]>sz[son[u]])son[u]=to[i]; } } inline void dfs2(int u,int ac) { In[u]=++cur,tp[u]=ac; if(son[u])dfs2(son[u],ac); for(int i=fir[u];i;i=nxt[i])if(to[i]!=fa[u]&&to[i]!=son[u])dfs2(to[i],to[i]); Out[u]=cur; } inline int LCA(int u,int v) { while(tp[u]!=tp[v]) { if(dpt[tp[u]]<dpt[tp[v]])swap(u,v); u=fa[tp[u]]; } return dpt[u]<dpt[v]?u:v; } inline void dp(int u) { sz[u]=P[u],f[u]=0,g[u]=P[u]?0:INF; for(int i=G[u].size()-1;~i;i--) { int v=G[u][i],w=dpt[v]-dpt[u]; dp(v); if(sz[u]>0)ans1=max(ans1,f[u]+w+f[v]),ans2=min(ans2,g[u]+w+g[v]); ans3+=w*(1ll*sz[v]*(N-sz[v])); f[u]=max(f[u],w+f[v]); g[u]=min(g[u],w+g[v]); sz[u]+=sz[v]; } P[u]=0;G[u].clear(); } inline void solve() { int K=N=getint();top=0; for(int i=1;i<=K;i++)P[h[i]=getint()]=1;h[++K]=1; sort(h+1,h+K+1,cmp); for(int i=K-1;i;i--)h[++K]=LCA(h[i],h[i+1]); sort(h+1,h+K+1,cmp);K=unique(h+1,h+K+1)-h-1; stk[++top]=1; for(int i=2;i<=K;i++) { while(top&&Out[stk[top]]<In[h[i]])top--; if(top)G[stk[top]].push_back(h[i]); stk[++top]=h[i]; } ans1=ans3=0,ans2=INF; dp(1); printf("%lld %lld %lld ",ans3,ans2,ans1); for(int i=1;i<=K;i++)sz[i]=0; } int main() { n=getint(); for(int i=1;i<n;i++) { int u=getint(),v=getint(); newnode(u,v),newnode(v,u); } dfs1(1),dfs2(1,1);memset(sz,0,sizeof sz); m=getint(); while(m--)solve(); }