1. 程式人生 > >題解 P3258 【[JLOI2014]松鼠的新家】

題解 P3258 【[JLOI2014]松鼠的新家】

更新 main continue putchar put inline graph pan dfs

這道題可以說是樹剖模板題。。。然而我一直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(\n); } } } using namespace Solve; int main () { // freopen(".in","r",stdin); // freopen(".out","w",stdout); solve(); }

題解 P3258 【[JLOI2014]松鼠的新家】