BZOJ 3631: [JLOI2014]松鼠的新家

题目描述

从出发点开始依次修改路径上的点权值,然后就是+1或-1的问题。

#include<complex>
#include<cstdio>
using namespace std;
const int N=3e5+7;
struct node{
    int v,nxt;
}e[N<<1];
int n,Enum,tim;
int front[N],a[N],tree[N<<2],lazy[N<<2];
int fat[N],son[N],siz[N],tid[N],top[N],dep[N];
int qread()
{
    int x=0;
    char ch=getchar();
    while(ch<'0' || ch>'9')ch=getchar();
    while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
void Insert(int u,int v)
{
    e[++Enum].v=v;
    e[Enum].nxt=front[u];
    front[u]=Enum;
}
void dfs1(int x)
{
    siz[x]=1;
    for(int i=front[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if(v==fat[x])continue;
        fat[v]=x;
        dep[v]=dep[x]+1;
        dfs1(v);
        siz[x]+=siz[v];
        if(siz[v]>siz[son[x]])
            son[x]=v;
    }
}
void dfs2(int x,int tp)
{
    top[x]=tp;
    tid[x]=++tim;
    if(!son[x])return;
    dfs2(son[x],tp);
    for(int i=front[x];i;i=e[i].nxt)
        if(e[i].v!=son[x] && e[i].v!=fat[x])
            dfs2(e[i].v,e[i].v);
}
void PushDown(int rt)
{
    if(lazy[rt])
    {
        tree[rt<<1]+=lazy[rt];
        tree[rt<<1|1]+=lazy[rt];
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    }
}
void Modify(int l,int r,int rt,int nowl,int nowr,int v)
{
    if(nowl<=l && r<=nowr)
    {
        tree[rt]+=v;
        lazy[rt]+=v;
        return;
    }
    PushDown(rt);
    int mid=l+r>>1;
    if(nowl<=mid)Modify(l,mid,rt<<1,nowl,nowr,v);
    if(mid<nowr)Modify(mid+1,r,rt<<1|1,nowl,nowr,v);
}
int Query(int l,int r,int rt,int p)
{
    if(l==r)return tree[rt];
    PushDown(rt);
    int mid=l+r>>1;
    if(p<=mid)return Query(l,mid,rt<<1,p);
    else return Query(mid+1,r,rt<<1|1,p);
}
void ModifyRoad(int x,int y)
{
    int f1=top[x],f2=top[y];
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y);
        Modify(1,n,1,tid[f1],tid[x],1);
        x=fat[f1];f1=top[x];
    }
    if(dep[x]>dep[y])swap(x,y);
    Modify(1,n,1,tid[x],tid[y],1);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        a[i]=qread();
    int u,v;
    for(int i=1;i<n;i++)
    {
        u=qread();v=qread();
        Insert(u,v);
        Insert(v,u);
    }
    dfs1(1);dfs2(1,1);
    int now=a[1];
    for(int i=2;i<=n;i++)
    {
        ModifyRoad(now,a[i]);
        now=a[i];
        Modify(1,n,1,tid[now],tid[now],-1);
    }
    for(int i=1;i<=n;i++)
        printf("%d
",Query(1,n,1,tid[i]));
    return 0;
}

另附一种树上差分的做法

#include<complex>
#include<cstdio>
using namespace std;
const int N=3e5+7;
struct node{
    int v,nxt;
}e[N<<1];
int n,Enum;
int front[N],cnt[N],a[N];
int fat[N],son[N],top[N],siz[N],dep[N];
int qread()
{
    int x=0;
    char ch=getchar();
    while(ch<'0' || ch>'9')ch=getchar();
    while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
void Insert(int u,int v)
{
    e[++Enum].v=v;
    e[Enum].nxt=front[u];
    front[u]=Enum;
}
void dfs1(int x)
{
    siz[x]=1;
    for(int i=front[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if(v==fat[x])continue;
        fat[v]=x;
        dep[v]=dep[x]+1;
        dfs1(v);
        siz[x]+=siz[v];
        if(siz[v]>siz[son[x]])
            son[x]=v;
    }
}
void dfs2(int x,int tp)
{
    top[x]=tp;
    if(!son[x])return;
    dfs2(son[x],tp);
    for(int i=front[x];i;i=e[i].nxt)
        if(e[i].v!=son[x] && e[i].v!=fat[x])
            dfs2(e[i].v,e[i].v);
}
int Lca(int x,int y)
{
    int f1=top[x],f2=top[y];
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y);
        x=fat[f1];f1=top[x];
    }
    if(dep[x]<dep[y])return x;
    return y;
}
void dfs3(int x)
{
    for(int i=front[x];i;i=e[i].nxt)
        if(e[i].v!=fat[x])
        {
            dfs3(e[i].v);
            cnt[x]+=cnt[e[i].v];
        }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        a[i]=qread();
    int u,v;
    for(int i=1;i<n;i++)
    {
        u=qread();v=qread();
        Insert(u,v);
        Insert(v,u);
    }
    dfs1(1);dfs2(1,1);
    int lca;
    for(int i=1;i<n;i++)
    {
        lca=Lca(a[i],a[i+1]);
        cnt[a[i]]++;cnt[a[i+1]]++;
        cnt[lca]--;cnt[fat[lca]]--;
    }
    dfs3(1);
    for(int i=2;i<=n;i++)
        cnt[a[i]]--;
    for(int i=1;i<=n;i++)
        printf("%d
",cnt[i]);
    return 0;
}
树上差分
原文地址:https://www.cnblogs.com/LeTri/p/8718321.html