[JLOI2014]松鼠的新家(树链剖分)

[JLOI2014]松鼠的新家(luogu)

Description

 

题目描述

 

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。

天哪,他居然真的住在”树“上。

松鼠想邀请****前来参观,并且还指定一份参观指南,他希望**能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家。

可是这样会导致**重复走很多房间,懒惰的**不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。

**是个馋家伙,立马就答应了。现在松鼠希望知道为了保证**有糖果吃,他需要在每一个房间各放至少多少个糖果。

因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当**在参观的最后到达餐厅时就不需要再拿糖果吃了。

 

输入格式

 

第一行一个整数n,表示房间个数第二行n个整数,依次描述a1-an

接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

 

输出格式

 

一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让**有糖果吃。

Solution

树链剖分区间加减(注意每次去另一个地方参观终点不用加一个糖果(=+1-1))

Code

#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
const int N=3e5+10;
vector <int> link[N];
struct node
{
    int l,r,lc,rc,tag,d;
}f[N*2];
int rt,top[N],si[N],fa[N],tot,cnt,n,u,v,
dfn[N],dep[N],son[N],c[N],q[N],re[N];
void dfs1(int u,int fx)
{
    dep[u]=dep[fx]+1,fa[u]=fx,si[u]=1;
    int size=link[u].size();
    for(int i=0;i<size;i++)
    {
        int v=link[u][i];
        if(v==fx) continue;
        dfs1(v,u);
        si[u]+=si[v];
        if(!son[u] || si[son[u]]<si[v]) son[u]=v;
    }
}
void dfs2(int u,int fx)
{
    dfn[u]=++tot,re[tot]=u;
    if(!son[u]) return ;
    top[son[u]]=top[u],dfs2(son[u],u);
    int size=link[u].size();
    for(int i=0;i<size;i++)
    {
        int v=link[u][i];
        if(v==son[u] || v==fx) continue;
        top[v]=v,dfs2(v,u);
    }
}
void build(int l,int r,int &g)
{
    g=++cnt,f[g].l=l,f[g].r=r;
    f[g].tag=0;
    if(l==r)
    {
        f[g].d=re[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,f[g].lc);
    build(mid+1,r,f[g].rc);
}
void add(int g,int l,int r)
{
    if(f[g].l==l && f[g].r==r)
    {
        f[g].tag++;
        return;
    }
    int mid=(f[g].l+f[g].r)>>1;
    if(r<=mid) add(f[g].lc,l,r);
    else if(l>mid) add(f[g].rc,l,r);
    else add(f[g].lc,l,mid),add(f[g].rc,mid+1,r);
}
void Add(int x,int y)
{
    int px=top[x],py=top[y];
    while(px!=py)
        if(dep[px]>=dep[py])
        {
            add(rt,dfn[px],dfn[x]);
            x=fa[px],px=top[x];
        }
        else
        {
            add(rt,dfn[py],dfn[y]);
            y=fa[py],py=top[y];
        }
    if(dfn[x]<=dfn[y]) add(rt,dfn[x],dfn[y]);
    else add(rt,dfn[y],dfn[x]);
}
void push_down(int g)
{
    if(f[g].tag==0) return ;
    f[f[g].lc].tag+=f[g].tag;
    f[f[g].rc].tag+=f[g].tag;
    f[g].tag=0;
}
void dfs(int g)
{
    if(f[g].l==f[g].r)
    {
        c[f[g].d]+=f[g].tag;
        return;
    }
    push_down(g);
    dfs(f[g].lc);
    dfs(f[g].rc);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&q[i]);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&u,&v);
        link[u].push_back(v);
        link[v].push_back(u);
    }
    dfs1(1,0);
    top[1]=1,dfs2(1,0);
    build(1,tot,rt);
    for(int i=2;i<=n;i++)
        Add(q[i-1],q[i]),c[q[i]]--;
    dfs(rt);
    for(int i=1;i<=n;i++)
        printf("%d\n",c[i]);
    return 0;
}

 

 

posted @ 2020-02-02 11:16  hsez_cyx  阅读(100)  评论(0)    收藏  举报