AC日记——[HNOI2014]世界树 bzoj 3572

3572

 

思路:

  虚树+乱搞;

 

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxn 300005
#define INF 0x3f3f3f3f
struct KiType {
    int id,key;
    bool operator<(const KiType pos)const
    {
        return key<pos.key;
    }
};
struct KiType ki[maxn];
int bel[maxn],dis[maxn],size[maxn],li[maxn],ri[maxn],lar[maxn],f[maxn];
int head[maxn],E[maxn<<1],V[maxn<<1],cnt,id[maxn],id_[maxn],deep[maxn];
int top[maxn],ai[maxn],sta[maxn],sum[maxn],n,m;
int W[maxn<<1];
bool vis[maxn],if_[maxn];
queue<int>que;
inline void in(int &now)
{
    char Cget=getchar();now=0;
    while(Cget>'9'||Cget<'0')Cget=getchar();
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
}
inline void edge_add(int u,int v)
{
    E[++cnt]=head[u],V[cnt]=v,head[u]=cnt;
    E[++cnt]=head[v],V[cnt]=u,head[v]=cnt;
}
inline void edge_add1(int u,int v)
{
    if(deep[u]<deep[v]) swap(u,v);
    int w=deep[u]-deep[v];
//    printf("%d %d %d\n",u,v,w);
    E[++cnt]=head[u],V[cnt]=v,W[cnt]=w,head[u]=cnt;
    E[++cnt]=head[v],V[cnt]=u,W[cnt]=w,head[v]=cnt;
}
void dfs1(int now,int fa)
{
    f[now]=fa,deep[now]=deep[fa]+1,size[now]=1;
    for(int i=head[now];i;i=E[i])
    {
        if(V[i]==fa) continue;
        dfs1(V[i],now),size[now]+=size[V[i]];
        if(size[V[i]]>size[lar[now]]) lar[now]=V[i];
    }
}
void dfs2(int now,int chain)
{
    top[now]=chain,id[now]=++cnt,id_[cnt]=now;
    if(lar[now]) dfs2(lar[now],chain);
    for(int i=head[now];i;i=E[i])
    {
        if(V[i]==lar[now]||V[i]==f[now]) continue;
        dfs2(V[i],V[i]);
    }
    ri[now]=cnt;
}
inline int find(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        x=f[top[x]];
    }
    return deep[x]<deep[y]?x:y;
}
inline int up(int now,int to)
{
    while(to<deep[top[now]]) now=f[top[now]];
    return id_[id[now]-deep[now]+to];
}
void Count(int now,int fa)
{
    int pos,pos_;
    if(!fa||bel[fa]==bel[now]) goto cur;
    pos=deep[now]-deep[fa]-1;
    if(pos)
    {
        pos_=(dis[fa]+pos+dis[now]+(bel[fa]<bel[now]?1:0))>>1;
        pos_=up(now,pos_-dis[fa]+deep[fa]+1);
        pos_=size[pos_]-size[now];
        sum[bel[now]]+=pos_,sum[bel[fa]]-=pos_;
    }
cur:
    sum[bel[now]]+=size[now];
    for(int i=head[now];i;i=E[i])
    {
        if(V[i]==fa) continue;
        sum[bel[now]]-=size[V[i]];
        Count(V[i],now);
    }
}
void clear(int now,int fa)
{
    for(int i=head[now];i;i=E[i])
    {
        if(fa==V[i]) continue;
        clear(V[i],now);
    }
    head[now]=0,sum[now]=0,dis[now]=0,vis[now]=false;
    bel[now]=0,dis[now]=INF;
}
int main()
{
    freopen("worldtree.in","r",stdin);
    freopen("worldtree.out","w",stdout);
    in(n);int u,v;
    for(int i=1;i<n;i++) in(u),in(v),edge_add(u,v);
    cnt=0,dfs1(1,0),dfs2(1,1),memset(head,0,sizeof(head));
    in(m);
    for(int i=1;i<=n;i++) dis[i]=INF;
    while(m--)
    {
        in(u),cnt=0;
        for(int i=1;i<=u;i++)
        {
            in(ki[i].id);
            ai[i]=ki[i].id;
            dis[ki[i].id]=0;
            vis[ki[i].id]=true;
            if_[ki[i].id]=true;
            que.push(ki[i].id);
            bel[ki[i].id]=ki[i].id;
            ki[i].key=id[ki[i].id];
        }
        sort(ki+1,ki+u+1),v=1,sta[v]=1;
        for(int i=1;i<=u;i++)
        {
            int now=ki[i].id,pos=0;
            if(sta[v]==now) continue;
            while(id[now]<li[sta[v]]||id[now]>ri[sta[v]])
            {
                if(pos) edge_add1(pos,sta[v]);
                pos=sta[v],v--;
            }
            if(pos)
            {
                int lca=find(pos,now);
                if(lca!=pos) edge_add1(pos,lca);
                if(lca!=sta[v]) sta[++v]=lca;
            }
            sta[++v]=now;
        }
        while(v>1) edge_add1(sta[v],sta[v-1]),v--;
        while(!que.empty())
        {
            int now=que.front();que.pop(),if_[now]=false;
            for(int i=head[now];i;i=E[i])
            {
                if(dis[V[i]]>dis[now]+W[i])
                {
                    dis[V[i]]=dis[now]+W[i];
                    bel[V[i]]=bel[now];
                    if(!if_[V[i]]) if_[V[i]]=true,que.push(V[i]);
                }
                else if(dis[V[i]]==dis[now]+W[i])
                {
                    if(bel[now]<bel[V[i]])
                    {
                        bel[V[i]]=bel[now];
                        if(!if_[V[i]]) if_[V[i]]=true,que.push(V[i]);
                    }
                }
            }
        }
        Count(1,0);
        for(int i=1;i<u;i++) printf("%d ",sum[ai[i]]);
        printf("%d \n",sum[ai[u]]);
        clear(1,0);
    }
    return 0;
}

 

posted @ 2017-06-09 15:22  IIIIIIIIIU  阅读(238)  评论(0编辑  收藏  举报