BZOJ 3611 [Heoi2014]大工程 ——虚树

虚树第二题。。。。

同BZOJ2286

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair
#define inf 0x3f3f3f3f
#define maxn 2000005
int h[maxn],to[maxn],ne[maxn],en=0;
int n,dep[maxn],st[maxn][22],in[maxn],out[maxn],ord[maxn],tot;
int _log[maxn],m,sta[maxn],top=0,se[maxn],idx,k,a[maxn];
 
void add(int a,int b)
{to[en]=b;ne[en]=h[a];h[a]=en++;}
 
void dfs1(int o,int fa)
{
    in[o]=++tot;ord[tot]=o;
    for (int i=h[o];i>=0;i=ne[i])
        if (to[i]!=fa)
        {
            dep[to[i]]=dep[o]+1;
            dfs1(to[i],o);
            ord[++tot]=o;
        }
    out[o]=tot;
}
 
void initst()
{
    F(i,2,maxn-1) _log[i]=_log[i>>1]+1;
    F(i,1,21) F(j,1,tot-(1<<i)+1)
    {
        if (dep[st[j][i-1]]<dep[st[j+(1<<i-1)][i-1]]) st[j][i]=st[j][i-1];
        else st[j][i]=st[j+(1<<i-1)][i-1];
    }
}
 
int lca(int l,int r)
{
    l=in[l];r=in[r];if (l==r) return st[l][0];
    if (l>r) swap(l,r);int tmp=_log[r-l+1];
    if (dep[st[l][tmp]]<dep[st[r-(1<<tmp)+1][tmp]]) return st[l][tmp];
    else return st[r-(1<<tmp)+1][tmp];
}
 
void debug()
{
    int a,b;
    while (scanf("%d%d",&a,&b)!=EOF)
        printf("%d
",lca(a,b));
}
 
bool cmp(int a,int b)
{
    return in[a]<in[b];
}
 
int hd[maxn],tl[maxn],nxt[maxn],ed,lst[maxn];
 
void add_edge(int a,int b)
{
    if (lst[a]!=idx) lst[a]=idx,hd[a]=-1;
    tl[ed]=b;
    nxt[ed]=hd[a];
    hd[a]=ed++;
}
 
int siz[maxn],mn[maxn],mx[maxn],ans_max,ans_min;
 
ll dfs2(int o,int fa)
{
    siz[o]=0;ll ret=0;
    mn[o]=inf;mx[o]=-inf;
    if (se[o]==idx) mn[o]=0,mx[o]=0,siz[o]++;
    for (int i=hd[o];i>=0;i=nxt[i])
    if (tl[i]!=fa){
        ret+=dfs2(tl[i],o);
        siz[o]+=siz[tl[i]];
        ans_max=max(ans_max,mx[o]+mx[tl[i]]+dep[tl[i]]-dep[o]);
        ans_min=min(ans_min,mn[o]+mn[tl[i]]+dep[tl[i]]-dep[o]);
        mn[o]=min(mn[o],mn[tl[i]]+dep[tl[i]]-dep[o]);
        mx[o]=max(mx[o],mx[tl[i]]+dep[tl[i]]-dep[o]);
    }
    for (int i=hd[o];i>=0;i=nxt[i])
    if (tl[i]!=fa){
        ret+=((ll)k-(ll)siz[tl[i]])*(ll)siz[tl[i]]*((ll)dep[tl[i]]-(ll)dep[o]);
    }
    return ret;
}
 
int main()
{
    memset(h,-1,sizeof h);
    scanf("%d",&n);
    F(i,2,n)
    {
        int a,b;scanf("%d%d",&a,&b);
        add(a,b);add(b,a);
    }
    dfs1(1,-1);
    F(i,1,tot) st[i][0]=ord[i]; initst();
    scanf("%d",&m);
    for (idx=1;idx<=m;++idx)
    {
        ed=0;
        scanf("%d",&k);
        F(i,1,k) scanf("%d",&a[i]);
        sort(a+1,a+k+1,cmp);
        int rt=a[1];F(i,2,k) rt=lca(rt,a[i]);
        sta[top=1]=rt;
        F(i,1,k)
        {
            se[a[i]]=idx; if (a[i]==rt) continue;
            int x=lca(a[i],sta[top]); //printf("Add and lca is %d
",x);
            while(dep[x]<dep[sta[top]])
            {
                int tmp;
                if (dep[x]>dep[sta[top-1]])tmp=x;
                else tmp=sta[top-1];
                add_edge(sta[top],tmp);
                add_edge(tmp,sta[top]);
                top--;
            }
            if (x!=sta[top]) sta[++top]=x;
            sta[++top]=a[i];
        }
        while (top>1) add_edge(sta[top],sta[top-1]),add_edge(sta[top-1],sta[top]),top--;
        ans_max=-inf;ans_min=inf;
        printf("%lld",dfs2(rt,0));
        printf(" %d %d
",ans_min,ans_max);
    }
}

  

原文地址:https://www.cnblogs.com/SfailSth/p/6669957.html