BZOJ 3307: 雨天的尾巴 线段树合并
写的好丑~
题解:
写权值线段树合并时一定要注意一件事情:是否是在线查询或者离线查询.
离线查询意味着在树上将该点所在线段树建出来后就要马上查询,因为在之后的合并中可能会该边结构.
这么做的好处就是比较省空间.
如果要在线查询,那么就一定在合并的时候不能直接将节点信息进行累加,而是每一次都要新建节点.
// luogu-judger-enable-o2 // luogu-judger-enable-o2 #include <cstdio> #include <algorithm> #define N 100005 #define ls t[x].lson #define rs t[x].rson #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) using namespace std; int n,m,edges,cnt; int hd[N],nex[N<<1],to[N<<1],fa[N],top[N],dep[N],siz[N],son[N]; int rt[N],tmp; struct Node { int lson,rson,max; }t[N*100]; inline void addedge(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } void dfs1(int u,int ff) { fa[u]=ff,dep[u]=dep[ff]+1,siz[u]=1; for(int i=hd[u];i;i=nex[i]) { int v=to[i]; if(v!=ff) { dfs1(v,u),siz[u]+=siz[v]; if(siz[v]>siz[son[u]]) son[u]=v; } } } void dfs2(int u,int tp) { top[u]=tp; if(son[u]) dfs2(son[u],tp); for(int i=hd[u];i;i=nex[i]) { int v=to[i]; if(v==fa[u]||v==son[u]) continue; dfs2(v,v); } } int LCA(int x,int y) { while(top[x]!=top[y]) { dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]; } return dep[x]<dep[y]?x:y; } void pushup(int x) { t[x].max=max(t[ls].max,t[rs].max); } int merge(int l,int r,int x,int y) { if(!x||!y) return x+y; int xx=++cnt; if(l==r) { t[xx].max=t[y].max+t[x].max; return xx; } int mid=(l+r)>>1; if(mid>=l) t[xx].lson=merge(l,mid,t[x].lson,t[y].lson); if(r>mid) t[xx].rson=merge(mid+1,r,t[x].rson,t[y].rson); pushup(xx); return xx; } void update(int l,int r,int &x,int p,int z) { if(!x)x=++cnt; if(l==r) { t[x].max+=z; return; } int mid=(l+r)>>1; if(p<=mid) update(l,mid,ls,p,z); else update(mid+1,r,rs,p,z); pushup(x); } void dfs(int u,int ff) { for(int i=hd[u];i;i=nex[i]) { int v=to[i]; if(v!=ff) dfs(v,u),rt[u]=merge(1,100000,rt[v],rt[u]); } } int find(int l,int r,int x) { if(l==r) return l; int mid=(l+r)>>1; if(t[ls].max==tmp) return find(l,mid,ls); else return find(mid+1,r,rs); } int main() { int i,j; // setIO("input"); scanf("%d%d",&n,&m); for(i=1;i<n;++i) { int a,b; scanf("%d%d",&a,&b),addedge(a,b),addedge(b,a); } dfs1(1,0),dfs2(1,1); for(i=1;i<=m;++i) { int x,y,z,lca; scanf("%d%d%d",&x,&y,&z); lca=LCA(x,y); update(1,100000,rt[x],z,1), update(1,100000,rt[y],z,1),update(1,100000,rt[lca],z,-1); if(fa[lca]) update(1,100000,rt[fa[lca]],z,-1); } dfs(1,0); for(i=1;i<=n;++i) { tmp=t[rt[i]].max; if(!tmp) printf("%d\n",tmp); else { printf("%d\n",find(1,100000,rt[i])); } } return 0; }