[线段树][树上差分] Jzoj P3397 雨天的尾巴
题解
- 考虑如果是在一条链上的话要怎么做
- 那么我们可以在x处加一个加入z的标记,在y+1出加入一个删掉z的标记,然后用权值线段树扫一遍就好了
- 现在拓展到一棵树上,我们可以在x和y处加入一个加上z的标记,在lca和fa[lca]处加入一个删除z的标记,那么我们每次可以把子节点的线段树合并上来
- 然后处理标记信息,最后查询答案即可
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <vector> 5 #define N 100010 6 using namespace std; 7 struct tree { int l,r,sum,v; }t[N*50]; 8 int n,m,cnt,deep[N],a[N],root[N],fa[N][18],ans[N]; 9 vector<int>e[N],p[N],q[N]; 10 void pushup(int x) { if (t[t[x].r].sum>t[t[x].l].sum) t[x].sum=t[t[x].r].sum,t[x].v=t[t[x].r].v; else t[x].sum=t[t[x].l].sum,t[x].v=t[t[x].l].v; } 11 void dfs(int x,int f,int dep) 12 { 13 fa[x][0]=f,deep[x]=dep,root[x]=x,cnt++; 14 for (int i=1;i<=17;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; 15 for (int i=0;i<e[x].size();i++) if (e[x][i]!=f) dfs(e[x][i],x,dep+1); 16 } 17 int LCA(int x,int y) 18 { 19 if (deep[x]<deep[y]) swap(x,y); 20 for (int i=17;i>=0;i--) if (deep[fa[x][i]]>=deep[y]) x=fa[x][i]; 21 if (x==y) return x; 22 for (int i=17;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; 23 return fa[x][0]; 24 } 25 int update(int &d,int l,int r,int x,int y) 26 { 27 if (!d) d=++cnt; 28 if (l==r) { t[d].sum+=y,t[d].v=l; return 0; } 29 int mid=l+r>>1; 30 if (x<=mid) update(t[d].l,l,mid,x,y); else update(t[d].r,mid+1,r,x,y); 31 pushup(d); 32 } 33 int merge(int x,int y,int l,int r) 34 { 35 if (!x) return y; 36 if (!y) return x; 37 if (l==r) { t[x].sum+=t[y].sum,t[x].v=l; return x; } 38 int mid=l+r>>1; 39 t[x].l=merge(t[x].l,t[y].l,l,mid),t[x].r=merge(t[x].r,t[y].r,mid+1,r); 40 pushup(x); return x; 41 } 42 void dfs1(int x,int pre) 43 { 44 for (int i=0;i<e[x].size();i++) if (e[x][i]!=pre) dfs1(e[x][i],x),merge(root[x],root[e[x][i]],1,N-10); 45 for (int i=0;i<p[x].size();i++) update(root[x],1,N-10,p[x][i],1); 46 for (int i=0;i<q[x].size();i++) update(root[x],1,N-10,q[x][i],-1); 47 ans[x]=t[root[x]].v; 48 } 49 int main() 50 { 51 scanf("%d%d",&n,&m); 52 for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),e[x].push_back(y),e[y].push_back(x); 53 dfs(1,0,1); 54 for (int i=1,x,y,z;i<=m;i++) 55 { 56 scanf("%d%d%d",&x,&y,&z); 57 int lca=LCA(x,y); 58 p[x].push_back(z),p[y].push_back(z),q[lca].push_back(z); 59 if (fa[lca][0]) q[fa[lca][0]].push_back(z); 60 } 61 dfs1(1,0); 62 for (int i=1;i<=n;i++) printf("%d\n",ans[i]); 63 }