雨天的尾巴
有了线段树合并的基础后,很容易想到差分最后线段树合并。
这道题跟hdu上的relief grain是重题,然而我们老师却把那道题当做树剖的练手题给我们。
害得我想了好久……
代码如下:
#include<bits/stdc++.h> using namespace std; const int maxn=2*1e5+10; int n,m,cnt; int beg[maxn],nex[maxn<<1],to[maxn<<1],e; inline void add(int x,int y){ e++;nex[e]=beg[x]; beg[x]=e;to[e]=y; } int dep[maxn],f[maxn][20]; struct node{ int l,r,ans,sum; }tr[maxn*50]; int rt[maxn],ans[maxn]; inline void dfs(int x,int fa){ dep[x]=dep[fa]+1; f[x][0]=fa; for(int i=1;i<=19;i++) f[x][i]=f[f[x][i-1]][i-1]; for(int i=beg[x];i;i=nex[i]) if(to[i]!=fa)dfs(to[i],x); } inline int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); for(int i=19;i>=0;i--) if(dep[x]-(1<<i)>=dep[y]) x=f[x][i]; if(x==y)return x; for(int i=19;i>=0;i--) if(f[x][i]!=f[y][i]){ x=f[x][i]; y=f[y][i]; } return f[x][0]; } inline void pushup(int now){ if(tr[tr[now].l].sum>=tr[tr[now].r].sum){ tr[now].sum=tr[tr[now].l].sum; tr[now].ans=tr[tr[now].l].ans; }else{ tr[now].sum=tr[tr[now].r].sum; tr[now].ans=tr[tr[now].r].ans; } } inline void update(int &now,int l,int r,int x,int val){ if(!now)now=++cnt; if(l==r){ tr[now].sum+=val; tr[now].ans=l; return; } int mid=(l+r)>>1; if(mid>=x)update(tr[now].l,l,mid,x,val); else update(tr[now].r,mid+1,r,x,val); pushup(now); } inline int merge(int a,int b,int l,int r){ if(!a)return b; if(!b)return a; if(l==r){ tr[a].sum+=tr[b].sum; tr[a].ans=l; return a; } int mid=(l+r)>>1; tr[a].l=merge(tr[a].l,tr[b].l,l,mid); tr[a].r=merge(tr[a].r,tr[b].r,mid+1,r); pushup(a); return a; } inline void solve(int x,int fa){ for(int i=beg[x];i;i=nex[i]){ int t=to[i]; if(t==fa)continue; solve(t,x); merge(rt[x],rt[t],1,maxn); } ans[x]=tr[rt[x]].ans; if(tr[rt[x]].sum==0)ans[x]=0; } inline int read(){ int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();} return x*f; } int main(){ n=read(),m=read(); for(int i=1;i<=n;i++)rt[i]=i; int x,y,z; for(int i=1;i<n;i++){ x=read(),y=read(); add(x,y),add(y,x); } dfs(1,0);cnt=n; for(int i=1;i<=m;i++){ x=read(),y=read(),z=read(); int t=lca(x,y); //printf("%d\n",t); update(rt[x],1,maxn,z,1); update(rt[y],1,maxn,z,1); update(rt[t],1,maxn,z,-1); if(f[t][0])update(rt[f[t][0]],1,maxn,z,-1); } solve(1,0); for(int i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; }
深深地感到自己的弱小。