洛谷P3258 [JLOI2014]松鼠的新家

@Pelom  October 12, 2021

题意

树上操作

  • $u$到$v$的路径上权值$+1$
  • 询问每个点的权值

数据范围:$2 \le n \le 300000$

题解

树剖裸题
注意每次的终点作为下次的起点,会多$+1$,记得$-1$;最后一次也是,题目有特殊要求

代码:

#include<iostream>
#include<cstdio>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
const int N=300000+10;
int n,u,v;
int a[N];
int cnt,tot;
int head[N],siz[N],fa[N],son[N],dep[N],top[N],id[N];
struct edge{
    int nxt,to;
} e[N<<1];
struct node{
    int w,tag;
    inline node():w(0),tag(0){}
} T[N<<2];
inline void add(int u,int v){
    e[++cnt]=edge{head[u],v};
    head[u]=cnt;
}
void dfs1(int u){
    siz[u]=1;
    dep[u]=dep[fa[u]]+1;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(v==fa[u])
            continue;
        fa[v]=u;
        dfs1(v);
        siz[u]+=siz[v];
        if(siz[son[u]]<siz[v])
            son[u]=v;
    }
}
void dfs2(int u,int t){
    top[u]=t;
    id[u]=++tot;
    if(!son[u])
        return ;
    dfs2(son[u],t);
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(v==fa[u] || v==son[u])
            continue;
        dfs2(v,v);
    }
}
inline void pushUp(int rt){
    T[rt].w=T[ls].w+T[rs].w;
}
inline void pushDown(int rt,int len){
    T[ls].w+=T[rt].tag*(len-(len>>1));
    T[rs].w+=T[rt].tag*(len>>1);
    T[ls].tag+=T[rt].tag;
    T[rs].tag+=T[rt].tag;
    T[rt].tag=0;
}
void update(int rt,int l,int r,int L,int R,int k){
    if(l>=L && r<=R){
        T[rt].w+=k*(r-l+1);
        T[rt].tag+=k;
        return ;
    }
    if(T[rt].tag!=0)
        pushDown(rt,r-l+1);
    int mid=l+r>>1;
    if(L<=mid)
        update(ls,l,mid,L,R,k);
    if(R>mid)
        update(rs,mid+1,r,L,R,k);
    pushUp(rt);
}
int query(int rt,int l,int r,int L,int R){
    if(l>=L && r<=R){
        return T[rt].w;
    }
    if(T[rt].tag!=0)
        pushDown(rt,r-l+1);
    int res=0;
    int mid=l+r>>1;
    if(L<=mid)
        res+=query(ls,l,mid,L,R);
    if(R>mid)
        res+=query(rs,mid+1,r,L,R);
    pushUp(rt);
    return res;
}
inline void Tupdate(int x,int y){
    for(;top[x]!=top[y];){
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        update(1,1,tot,id[top[x]],id[x],1);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])
        swap(x,y);
    update(1,1,tot,id[x],id[y],1);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    dfs1(1);
    dfs2(1,1);
    for(int i=1;i<n;i++){
        Tupdate(a[i],a[i+1]);
        update(1,1,tot,id[a[i+1]],id[a[i+1]],-1);
    }
    for(int i=1;i<=n;i++)
        printf("%d\n",query(1,1,tot,id[i],id[i]));
    return 0;
}

添加新评论