[Vani有约会]雨天的尾巴 (线段树合并)
题目链接
Solution
树上差分+线段树合并.
在每个节点上维护一棵权值线段树.
然后如果需要修改 \(x,y\) 两点,则在 \(x\) 处和 \(y\) 处分别加上 \(1\) 的权值.
然后在 \(lca(x,y)\) 以及 \(fa[lca(x,y)]\) 处减掉 \(1\) .
最后面 \(dfs\) 从下往上更新.
由于每一次维护只维护四个点的值,且每次在每一棵树上也只会修改一条链的值.
每次操作时间复杂度和空间复杂度均为 \(O(4*logn)\) .
所以整体时间和空间复杂度即为 \(O(4*nlogn)\) .可以过.
Code
#include<bits/stdc++.h>
#define N 100008
#define in(x) x=read()
using namespace std;
struct sj{int to,next;}a[N*2];
int head[N*2],size,n,q;
int dep[N*2],fa[N*2][20],v[N*2];
int T[N*2],L[N*60],R[N*60],rans[N*2];
int num[N*60],rt,tot,m,Ans[N*60],ans[N*60];
int read()
{
char ch=getchar(); int f=1,w=0;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
return f*w;
}
void add(int x,int y)
{
a[++size].to=y;
a[size].next=head[x];
head[x]=size;
}
void dfs(int x,int fr)
{
for(int i=head[x];i;i=a[i].next){
int tt=a[i].to;
if(tt==fr)continue;
dep[tt]=dep[x]+1;
fa[tt][0]=x;
dfs(tt,x);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=19;i>=0;i--)
if(dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if(x==y) return x;
for(int i=19;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
void pushup(int node)
{
if(ans[L[node]]>=ans[R[node]])
ans[node]=ans[L[node]],Ans[node]=Ans[L[node]];
else
ans[node]=ans[R[node]],Ans[node]=Ans[R[node]];
}
void update(int &node,int l,int r,int pos,int v)
{
if(!node) node=++tot;
if(l==r) {ans[node]+=v;Ans[node]=l;return;}
int mid=(l+r)/2;
if(pos<=mid) update(L[node],l,mid,pos,v);
else update(R[node],mid+1,r,pos,v);
if(l!=r)
pushup(node);
}
int merge(int x,int y,int l,int r)
{
if(l==r&&x&&y) ans[x]+=ans[y];
if(!x||!y) return x+y;
int mid=(l+r)/2;
L[x]=merge(L[x],L[y],l,mid);
R[x]=merge(R[x],R[y],mid+1,r);
if(l!=r)
pushup(x);
return x;
}
void Dfs(int x,int fr)
{
for(int i=head[x];i;i=a[i].next){
int tt=a[i].to;
if(tt==fr)continue;
Dfs(tt,x);
T[x]=merge(T[x],T[tt],1,N);
}
if(ans[T[x]]>0)
rans[x]=Ans[T[x]];
}
int main()
{
in(n),in(q);
for(int i=1;i<n;i++){
int x,y; in(x),in(y);
add(x,y),add(y,x);
}
dep[1]=1; dfs(1,0);
for(int j=1;j<=19;j++)
for(int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
for(int i=1;i<=q;i++)
{
int x,y,z;
in(x),in(y),in(z);
int pp=lca(x,y);
update(T[x],1,N,z,1);
update(T[y],1,N,z,1);
update(T[pp],1,N,z,-1);
update(T[fa[pp][0]],1,N,z,-1);
}
Dfs(1,0);
for(int i=1;i<=n;i++)
printf("%d\n",rans[i]);
}