Luogu_P4556 雨天的尾巴【题解】树上差分 线段树合并
题面:https://www.luogu.com.cn/problem/P4556
对于在一条(x,y)路径上将z加1。
就可以树上差分。
x和y都是加1。lca是减1,lca的father也是减1。
但是由于又有很多种不一样的种类。
还需要每个点维护一个线段树。
合并的时候求哪个种类是max。
最后统计答案dfs。
思路简单,主要是代码长。
代码如下:
#pragma-GCC-optimize("O2,Ofast,inline,unroll-all-loops,-ffast-math") #pragma-GCC-target("avx,sse2,sse3,sse4,popcnt") #include<bits/stdc++.h> using namespace std; const int maxn=100010; int tt,n,m; struct node{ int nxt,to; #define nxt(x) e[x].nxt #define to(x) e[x].to }e[maxn<<1]; int head[maxn],tot,dep[maxn],f[maxn][21],rt[maxn],num,cnt,X[maxn],Y[maxn],Z[maxn],val[maxn],ans[maxn]; inline void add(int x,int y){ to(++tot)=y; nxt(tot)=head[x];head[x]=tot; } queue<int> q; inline long read(){ long x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f*=-1;c=getchar();} while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x*f; } inline void bfs(){ q.push(1);dep[1]=1; while(q.size()){ int x=q.front();q.pop(); for(int i=head[x];i;i=nxt(i)){ int to=to(i); if(dep[to]) continue; dep[to]=dep[x]+1; f[to][0]=x; for(int j=1;j<=tt;j++) f[to][j]=f[f[to][j-1]][j-1]; q.push(to); } } } inline int lca(int x,int y){ if(dep[x]>dep[y]) swap(x,y); for(int i=tt;i>=0;i--) if(dep[f[y][i]] >= dep[x]) y=f[y][i]; if(x==y) return x; for(int i=tt;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } struct tree{ int lc,rc,dt,tg; }t[maxn*80]; void insert(int p,int l,int r,int vl,int d){ if(l==r){ t[p].dt+=d; t[p].tg=t[p].dt ? l : 0 ; return; } int mid=(l+r)>>1; if(vl<=mid){ if(!t[p].lc) t[p].lc=++num; insert(t[p].lc,l,mid,vl,d); }else{ if(!t[p].rc) t[p].rc=++num; insert(t[p].rc,mid+1,r,vl,d); } t[p].dt=max(t[t[p].lc].dt,t[t[p].rc].dt); t[p].tg=t[t[p].lc].dt>=t[t[p].rc].dt ? t[t[p].lc].tg : t[t[p].rc].tg; } int merge(int p,int q,int l,int r){ if(!p) return q; if(!q) return p; if(l==r){ t[p].dt+=t[q].dt; t[p].tg=t[p].dt ? l : 0; return p; } int mid=(l+r)>>1; t[p].lc=merge(t[p].lc,t[q].lc,l,mid); t[p].rc=merge(t[p].rc,t[q].rc,mid+1,r); t[p].dt=max(t[t[p].lc].dt,t[t[p].rc].dt); t[p].tg=t[t[p].lc].dt>=t[t[p].rc].dt ? t[t[p].lc].tg : t[t[p].rc].tg; return p; } void dfs(int x){ for(int i=head[x];i;i=nxt(i)){ int to=to(i); if(dep[to]<=dep[x]) continue; dfs(to); rt[x]=merge(rt[x],rt[to],1,cnt); } ans[x]=t[rt[x]].tg; } int main() { n=read(),m=read(); tt=(int)(log(n)/log(2))+1; for(int i=1;i<n;i++){ int x,y;x=read();y=read(); add(x,y);add(y,x); } bfs(); for(int i=1;i<=n;i++) rt[i]=++num; for(int i=1;i<=m;i++){ X[i]=read();Y[i]=read();Z[i]=read(); val[i]=Z[i]; } sort(val+1,val+1+m); cnt=unique(val+1,val+1+m)-val-1; for(int i=1;i<=m;i++){ int x=X[i],y=Y[i]; int z=lower_bound(val+1,val+1+cnt,Z[i])-val; int lc=lca(x,y); insert(rt[x],1,cnt,z,1); insert(rt[y],1,cnt,z,1); insert(rt[lc],1,cnt,z,-1); if(f[lc][0]) insert(rt[f[lc][0]],1,cnt,z,-1); } dfs(1); for(int i=1;i<=n;i++) printf("%d\n",val[ans[i]]); return 0; }