题解 P3258 [JLOI2014]松鼠的新家

Posted ilverene

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 P3258 [JLOI2014]松鼠的新家相关的知识,希望对你有一定的参考价值。

这道题可以说是树剖模板题。。。然而我一直WA10找不出错误。。。后来才发现是手抖打少了一个两个字符。。。


 

其实题目说的就是给你一颗树和一个遍历顺序,然后按照遍历顺序更新路径的值,最后查询所有节点的值。

其实这种题用树上差分会更理想,但是为了练树剖也就写了树剖。


 

AC代码如下:

1097ms 56696kb

#include<bits/stdc++.h>

using namespace std;

namespace StandardIO {

    template<typename T>inline void read (T &x) {
        x=0;T f=1;char c=getchar();
        for (; c<0||c>9; c=getchar()) if (c==-) f=-1;
        for (; c>=0&&c<=9; c=getchar()) x=x*10+c-0;
        x*=f;
    }

    template<typename T>inline void write (T x) {
        if (x<0) putchar(-),x*=-1;
        if (x>=10) write(x/10);
        putchar(x%10+0);
    }

}

using namespace StandardIO;

namespace Solve {
    
    const int N=300300;
    
    int n;
    int a[N];
    vector<int>graph[N];
    int index;
    int fa[N],dep[N],size[N],son[N],dfn[N],top[N];
    struct node {
        int l,r,val,tag;
    }tree[N<<2];
    
    void dfs1 (int now,int father) {
        fa[now]=father,dep[now]=dep[father]+1,size[now]=1;
        for (register int i=0; i<graph[now].size(); ++i) {
            int to=graph[now][i];
            if (to==father) continue;
            dfs1(to,now);
            size[now]+=size[to];
            if (size[to]>size[son[now]]) son[now]=to;
        }
    }
    void dfs2 (int now,int topf) {
        dfn[now]=++index,top[now]=topf;
        if (!son[now]) return;
        dfs2(son[now],topf);
        for (register int i=0 ;i<graph[now].size(); ++i) {
            int to=graph[now][i];
            if (to==fa[now]||to==son[now]) continue;
            dfs2(to,to);
        }
    }
    inline void pushup (int pos) {
        tree[pos].val=tree[pos<<1].val+tree[pos<<1|1].val;
    }
    inline void pushdown (int pos) {
        if (tree[pos].tag) {
            tree[pos<<1].tag+=tree[pos].tag,tree[pos<<1|1].tag+=tree[pos].tag;
            tree[pos<<1].val+=(tree[pos<<1].r-tree[pos<<1].l+1)*tree[pos].tag;
            tree[pos<<1|1].val+=(tree[pos<<1|1].r-tree[pos<<1|1].l+1)*tree[pos].tag;
            tree[pos].tag=0;
        }
    }
    void build (int l,int r,int pos) {
        tree[pos].l=l,tree[pos].r=r,tree[pos].val=tree[pos].tag=0;
        if (l==r) return;
        int mid=(l+r)>>1;
        build(l,mid,pos<<1),build(mid+1,r,pos<<1|1);
        pushup(pos);
    }
    void update (int l,int r,int v,int pos) {
        if (l<=tree[pos].l&&tree[pos].r<=r) {
            tree[pos].val+=v,tree[pos].tag+=v;
            return;
        }
        pushdown(pos);
        int mid=(tree[pos].l+tree[pos].r)>>1;
        if (l<=mid) update(l,r,v,pos<<1);
        if (mid<r) update(l,r,v,pos<<1|1);
        pushup(pos);
    }
    int query (int l,int r,int pos) {
        if (l<=tree[pos].l&&tree[pos].r<=r) {
            return tree[pos].val;
        }
        pushdown(pos);
        int mid=(tree[pos].l+tree[pos].r)>>1,ans=0;
        if (l<=mid) ans+=query(l,r,pos<<1);
        if (mid<r) ans+=query(l,r,pos<<1|1);
        return ans;
    }
    inline void updatePath (int x,int y,int v) {
        while (top[x]!=top[y]) {
            if (dep[top[x]]<dep[top[y]]) swap(x,y);
            update(dfn[top[x]],dfn[x],v,1);
            x=fa[top[x]];
        }
        if (dep[x]>dep[y]) swap(x,y);
        update(dfn[x],dfn[y],v,1);
    }
    inline int queryNode (int x) {
        return query(dfn[x],dfn[x],1);
    }

    inline void solve () {
        read(n);
        for (register int i=1; i<=n; ++i) {
            read(a[i]);
        }
        for (register int i=1; i<=n-1; ++i) {
            int x,y;
            read(x),read(y);
            graph[x].push_back(y);
            graph[y].push_back(x);
        }
        dfs1(1,0);
        dfs2(1,1);
        build(1,n,1);
        for (register int i=1; i<=n-1; ++i) {
            updatePath(a[i],a[i+1],1);
        }
        for (register int i=1; i<=n; ++i) {
            write((i==a[1])?queryNode(i):queryNode(i)-1),putchar(
);
        }
    }
}

using namespace Solve;

int main () {
//    freopen(".in","r",stdin);
//    freopen(".out","w",stdout);
    solve();
}

 

以上是关于题解 P3258 [JLOI2014]松鼠的新家的主要内容,如果未能解决你的问题,请参考以下文章

P3258 [JLOI2014]松鼠的新家

洛谷lca+树上差分P3258 [JLOI2014]松鼠的新家

Luogu P3258[JLOI2014]松鼠的新家

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

BZOJ 3631 [JLOI2014]松鼠的新家

BZOJ 3631 [JLOI2014]松鼠的新家 | 树上差分