「luogu3258」[JLOI2014] 松鼠的新家
https://www.luogu.org/problemnew/show/P3258
(树剖裸题
树上差分 = = 差分 + lca
1. 树上差分基本思想:和差分一样,用前缀和的思想来处理解(操作后的树上,任意节点的糖果数 是通过所有与其相连的子节点的和 以及该节点在差分数组里的值 得到的(dfs);
2. 因为这道题并不需要除了lca以外的信息,故tarjan
对于一组修改u,v :只需修改差分数组 ----- diff[u]++, diff[v], diff[lca(u,v)]--, diff[fa[lca(u,v)]]--
至于为什么,看1;
剩下自己想;;
// 15owzLy1 //luogu3258.cpp //2018 09 25 18:45:43 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> typedef long long ll; typedef double db; using namespace std; const int N = 300005; struct node { int next, to; }edge[N<<1]; int set_[N], candy[N], diff[N], n, head[N], head_q[N], fa[N]; int query[N][2], a, b, c, cnt; bool vis[N]; template<typename T>inline void read(T &x_) { x_=0;bool f_=0;char c_=getchar(); while(c_<'0'||c_>'9'){f_|=(c_=='-');c_=getchar();} while(c_>='0'&&c_<='9'){x_=(x_<<1)+(x_<<3)+(c_^48);c_=getchar();} x_=f_?-x_:x_; } inline void jb(int u, int v) { edge[++cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; } int get_set_(int x) { return (set_[x]==x)?x:set_[x]=get_set_(set_[x]); } inline void Merge(int x, int y) { set_[get_set_(y)]=get_set_(x); } void dfs(int u) { vis[u]=true; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(v==fa[u]) continue; fa[v]=u; dfs(v); Merge(u, v); } if(vis[query[u][0]]) { a=get_set_(query[u][0]); if(a!=get_set_(u)) { diff[a]--, diff[fa[a]]--; diff[u]++, diff[query[u][0]]++; } } if(vis[query[u][1]]) { a=get_set_(query[u][1]); if(a!=get_set_(u)) { diff[a]--, diff[fa[a]]--; diff[query[u][1]]++, diff[u]++; } } } void get_ans(int u) { candy[u]=diff[u]; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(v==fa[u]) continue; get_ans(v); candy[u]+=candy[v]; } } int main() { #ifndef ONLINE_JUDGE freopen("luogu3258.in","r",stdin); freopen("luogu3258.out","w",stdout); #endif int x, y, a1; read(n); read(x); a1=x; for(int i=1;i<n;i++) { read(y); query[y][0]=x, query[x][1]=y; x=y; } for(int i=1;i<n;i++) read(x), read(y), jb(x, y), jb(y, x); for(int i=1;i<=n;i++) set_[i]=i; dfs(1); get_ans(1); candy[a1]++; for(int i=1;i<=n;i++) printf("%d\n", candy[i]-1); return 0; }