码迷,mamicode.com
首页 > 其他好文 > 详细

HEOI2014 大工程

时间:2020-01-05 22:44:48      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:pac   lan   一个   swap   close   hid   http   inf   string   

题目传送门

分析:

虚数模板练习,只是在这里放个码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\n",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();
}
View Code

技术图片

HEOI2014 大工程

标签:pac   lan   一个   swap   close   hid   http   inf   string   

原文地址:https://www.cnblogs.com/Darknesses/p/12153728.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!