[Explanations] Luogu P5327 [ZJOI2019] language

Original title Portal

Such statistics point to see the trees for the title number is generally segment tree merger, this problem is not unexpected

First the tree for this cross-sectional tree, for each universal language, in \ (x, y \) a line segment of two tree \ (x, y \) play two positions \ (1 + \) marker at the point \ (fa [lca (x, y)] \) segment tree \ (x, y \) two positions hit \ (- 2 \) labeled

Tree line in the maintenance of three things:

1.dfs minimal sequence \ (LP \)

2.dfs sequence biggest \ (rp \)

3. All the segment tree is a point marking the path to the root node and the node number \ (SUM \)

We search and upward from the lower segment tree merger, for each node, the contribution of the answer is the root node of the tree line of \ (sum-dep [lca ( lp, rp)] + 1-1 \) (Ke to understand how the drawing)

Pay up, wa found, because the contribution of each path is that we forget \ (2 \) times, it can be divided by 2

#include <bits/stdc++.h>
#define N 100005 
#define ll long long 
#define getchar nc
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register ll x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
int n,m;
ll ans;
struct edge{
    int to,next;
}e[N<<1];
int head[N],cnt=0;
inline void add(register int u,register int v)
{
    e[++cnt]=(edge){v,head[u]};
    head[u]=cnt;
}
int size[N],fa[N],son[N],dep[N],top[N],dfn[N],tim,idfn[N];
inline void dfs1(register int x)
{
    size[x]=1;
    for(register int i=head[x];i;i=e[i].next)
    {
        int v=e[i].to;
        if(v==fa[x])
            continue;
        dep[v]=dep[x]+1;
        fa[v]=x;
        dfs1(v);
        size[x]+=size[v];
        if(size[v]>size[son[x]])
            son[x]=v;
    }
}
inline void dfs2(register int x,register int t)
{
    dfn[x]=++tim;
    idfn[tim]=x;
    top[x]=t;
    if(son[x])
        dfs2(son[x],t);
    for(register int i=head[x];i;i=e[i].next)
    {
        int v=e[i].to;
        if(v!=fa[x]&&v!=son[x])
            dfs2(v,v);
    }
}
inline int getlca(register int x,register int y)
{
    int fx=top[x],fy=top[y];
    while(fx!=fy)
    {
        if(dep[fx]<dep[fy])
        {
            x^=y^=x^=y;
            fx^=fy^=fx^=fy;
        }
        x=fa[fx];
        fx=top[x];
    }
    return dep[x]<dep[y]?x:y;
}
int root[N],tot;
struct node{
    int ls,rs,cnt,lp,rp,sum;
}tr[N*60];
inline void pushup(register int x)
{
    tr[x].lp=tr[tr[x].ls].lp?tr[tr[x].ls].lp:tr[tr[x].rs].lp;
    tr[x].rp=tr[tr[x].rs].rp?tr[tr[x].rs].rp:tr[tr[x].ls].rp;
    tr[x].sum=tr[tr[x].ls].sum+tr[tr[x].rs].sum;
    if(tr[tr[x].ls].rp&&tr[tr[x].rs].lp)
        tr[x].sum-=dep[getlca(tr[tr[x].ls].rp,tr[tr[x].rs].lp)];
}
inline void modify(register int &x,register int l,register int r,register int pos,register int val)
{
    if(!x)
        x=++tot;
    if(l==r)
    {
        tr[x].cnt+=val;
        if(tr[x].cnt)
            tr[x].lp=tr[x].rp=pos,tr[x].sum=dep[pos];
        else
            tr[x].lp=tr[x].rp=tr[x].sum=0;
        return;
    }
    int mid=l+r>>1;
    if(dfn[pos]<=mid)
        modify(tr[x].ls,l,mid,pos,val);
    else
        modify(tr[x].rs,mid+1,r,pos,val);
    pushup(x);
}
inline void merge(register int &a,register int b,register int l,register int r)
{
    if(!a||!b)
    {
        a=a+b;
        return;
    }
    if(l==r)
    {
        tr[a].cnt+=tr[b].cnt;
        if(tr[a].cnt)
            tr[a].lp=tr[a].rp=idfn[l],tr[a].sum=dep[idfn[l]];
        else
            tr[a].lp=tr[a].rp=tr[a].sum=0;
        return;
    }
    int mid=l+r>>1;
    merge(tr[a].ls,tr[b].ls,l,mid);
    merge(tr[a].rs,tr[b].rs,mid+1,r);
    pushup(a);
}
inline void dfs(register int x)
{
    for(register int i=head[x];i;i=e[i].next)
    {
        int v=e[i].to;
        if(v==fa[x])
            continue;
        dfs(v);
        merge(root[x],root[v],1,tim);
    }
    if(tr[root[x]].lp&&tr[root[x]].rp)
        ans+=tr[root[x]].sum-dep[getlca(tr[root[x]].lp,tr[root[x]].rp)];
}
int main()
{
    n=read(),m=read();
    for(register int i=1;i<n;++i)
    {
        int u=read(),v=read();
        add(u,v),add(v,u);
    }
    dfs1(1);
    dfs2(1,0);
    for(register int i=1;i<=m;++i)
    {
        int x=read(),y=read();
        int lca=getlca(x,y);
        modify(root[x],1,tim,x,1);
        modify(root[x],1,tim,y,1);
        modify(root[y],1,tim,x,1);
        modify(root[y],1,tim,y,1);
        if(lca>1)
        {
            modify(root[fa[lca]],1,tim,x,-2);
            modify(root[fa[lca]],1,tim,y,-2);
        }
    }
    dfs(1);
    write(ans>>1);
    return 0;
}

Guess you like

Origin www.cnblogs.com/yzhang-rp-inf/p/11223298.html