雨天的尾巴
P4556雨天的尾巴
先考虑修改操作,因为要对$x \to y $ 路径上的每一个点的\(Z\) 类物品加一,所以我们考虑树上差分,在\(x点和y点\)上\(+1\)然后在\(lca(x,y)\)和\(fa_{lca(x,y)}\)位置\(-1\)
然后我们可以从叶子节点到根节点做一遍\(dfs\)每次把儿子线段树的每一个点合并到父亲线段树上,维护最大值和物品编号
不会线段树合并的可以看这个
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,C=1e5+5;
int hd[N],cnt,sz[N],son[N],top[N],tp[N],a[N],fa[N],dep[N],u,v,w,ps,n,m;
struct E {
int to,nt;
}e[N << 1];
struct Tr {
int clr,v,l,r;
}tr[10000007];
void add(int x,int y) {
e[++cnt].to = y;
e[cnt].nt = hd[x];
hd[x] = cnt;
}
void dfs1(int x) {
int y,maxs = 0;
sz[x] = 1;
for(int i=hd[x];i;i=e[i].nt) {
y = e[i].to;
if(y == fa[x] )
continue;
fa[y] = x;
dep[y] = dep[x] + 1;
dfs1(y);
sz[x] += sz[y];
if(sz[y] > maxs) {
maxs = sz[y];
son[x] = y;
}
}
}
void dfs2(int x) {
if(son[x]) {
top[son[x]] = top[x];
dfs2(son[x]);
}
int y;
for(int i=hd[x];i;i=e[i].nt) {
y=e[i].to;
if(y == fa[x] || y == son[x])
continue;
top[y] = y;
dfs2(y);
}
}
int lca(int x,int y) {
while(top[x] != top[y]) {
if(dep[fa[top[x]]] > dep[fa[top[y]]])
swap(x,y);
y = fa[top[y]];
}
if(dep[x] > dep[y])
swap(x,y);
return x;
}
void get_l(int p) {
if(!tr[p].l)
tr[p].l = ++ps;
}
void get_r(int p) {
if(!tr[p].r)
tr[p].r = ++ps;
}
void updata(int p) {
if(tr[tr[p].l].v > tr[tr[p].r].v) {
tr[p].v = tr[tr[p].l].v;
tr[p].clr = tr[tr[p].l].clr;
}
else if(tr[tr[p].l].v < tr[tr[p].r].v){
tr[p].v = tr[tr[p].r].v;
tr[p].clr = tr[tr[p].r].clr;
}
else {
tr[p].v = tr[tr[p].l].v;
tr[p].clr = tr[tr[p].l].clr;
}
}
void change(int p,int l,int r,int cl,int vl) {
if(l==r) {
tr[p].clr = cl;
tr[p].v += vl;
}
else {
int mid=l + r >> 1;
if(cl <= mid) {
get_l(p);
change(tr[p].l,l,mid,cl,vl);
}
else {
get_r(p);
change(tr[p].r,mid+1,r,cl,vl);
}
updata(p);
}
}
void Marge(int x,int y,int l,int r) {
if(l == r) {
tr[x].v+=tr[y].v;
}
else {
int mid = l + r >> 1;
if(!tr[x].l && tr[y].l) {
tr[x].l = tr[y].l;
}
else if(tr[y].l && tr[x].l) {
Marge(tr[x].l,tr[y].l,l,mid);
}
if(!tr[x].r && tr[y].r) {
tr[x].r = tr[y].r;
}
else if(tr[y].r && tr[x].r) {
Marge(tr[x].r,tr[y].r,mid+1,r);
}
updata(x);
}
}
void fans(int x) {
int y;
for(int i=hd[x];i;i=e[i].nt) {
y=e[i].to;
if(fa[x] == y)
continue;
fans(y);
Marge(x,y,1,C);
}
}
int main() {
int la;
scanf("%d%d",&n,&m);
ps=n;
for(int i=1;i<n;i++) {
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
dep[1] = 1;
dfs1(1);
top[1] = 1;
dfs2(1);
for(int i=1;i<=m;i++) {
scanf("%d%d%d",&u,&v,&w);
change(u,1,C,w,1);
change(v,1,C,w,1);
la = lca(u,v);
change(la,1,C,w,-1);
change(fa[la],1,C,w,-1);
}
fans(1);
for(int i=1;i<=n;i++)
{
if(tr[i].v)
printf("%d\n",tr[i].clr);
else
printf("0\n");
}
return 0;
}
如果人生会有很长,愿有你的荣耀永不散场