题解 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]松鼠的新家的主要内容,如果未能解决你的问题,请参考以下文章