[BZOJ] 3307: 雨天的尾巴
题意:给一颗树,每次在一条路径上增加一种物品,问每个点为根的子树中最多的物品的种类
每个点维护一颗权值线段树,树上差分,复杂度O((n+m)logn)
实际操作中,权值线段树叶子节点维护出现次数,非叶子节点维护子树max值和出现位置,其实也可以只维护max值,统计答案时二分统计
第一个版本是直接开了1~1e9的权值线段树,常数较大
#include<iostream> #include<cstdio> using namespace std; const int MAXN=100005*60; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } struct Edge{ int next,to; }e[MAXN<<1]; int ecnt,head[MAXN]; inline void add(int x,int y){ e[++ecnt].next = head[x]; e[ecnt].to = y; head[x] = ecnt; } int dep[MAXN],fa[MAXN],hson[MAXN],siz[MAXN]; void dfs1(int x,int pre){ dep[x]=dep[pre]+1;fa[x]=pre;siz[x]=1; int sz=0; for(int i=head[x];i;i=e[i].next){ int v=e[i].to; if(v==pre)continue; dfs1(v,x);siz[x]+=siz[v]; if(siz[v]>sz){sz=siz[v];hson[x]=v;} } } int top[MAXN]; void dfs2(int x,int tp){ top[x]=tp; if(hson[x])dfs2(hson[x],tp); for(int i=head[x];i;i=e[i].next){ int v=e[i].to; if(v==fa[x]||v==hson[x])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; } int rt[MAXN],num; int val[MAXN],mx[MAXN],mxp[MAXN],ch[MAXN][2]; inline int newnode(){return ++num;} inline void pushup(int cur){ int x=ch[cur][0],y=ch[cur][1]; int u=mx[x]<mx[y]; mxp[cur]=mxp[ch[cur][u]]; mx[cur]=mx[ch[cur][u]]; } void update(int x,int &cur,int l,int r,int w){ if(!cur)cur=newnode(); if(l==r){mx[cur]+=w;mxp[cur]=l;return;} int mid=(l+r)>>1; if(x<=mid)update(x,ch[cur][0],l,mid,w); else update(x,ch[cur][1],mid+1,r,w); pushup(cur); } void merge(int &u,int v,int l,int r){ if(!u||!v) {u=u+v;return;} if(l==r){ mx[u]+=mx[v]; mxp[u]=l; return; } int mid=(l+r)>>1; merge(ch[u][0],ch[v][0],l,mid); merge(ch[u][1],ch[v][1],mid+1,r); pushup(u); } int n,m; struct Node{ int x,y,w; }a[MAXN]; int tmp[MAXN],ans[MAXN]; void dfs(int x){ for(int i=head[x];i;i=e[i].next){ int v=e[i].to; if(v==fa[x])continue; dfs(v); merge(rt[x],rt[v],1,1e9); } ans[x]=mxp[rt[x]]; } int main(){ n=rd();m=rd(); int x,y,w; for(int i=1;i<n;i++){ x=rd();y=rd(); add(x,y);add(y,x); } dfs1(1,0);dfs2(1,1); for(register int i=1;i<=m;i++){ x=rd();y=rd();tmp[i]=w=rd(); update(w,rt[x],1,1e9,1); update(w,rt[y],1,1e9,1); int l=lca(x,y); update(w,rt[l],1,1e9,-1); if(l=fa[l])update(w,rt[l],1,1e9,-1); } dfs(1); for(register int i=1;i<=n;i++){ printf("%d\n",ans[i]); } }
第二个版本先离散化,开一棵1~m的权值线段树,快了一倍qwq
#include<algorithm> #include<iostream> #include<cstdio> using namespace std; const int MAXN=100005; const int N=MAXN*60; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } struct Edge{ int next,to; }e[MAXN<<1]; int ecnt,head[MAXN]; inline void add(int x,int y){ e[++ecnt].next = head[x]; e[ecnt].to = y; head[x] = ecnt; } int dep[MAXN],fa[MAXN],hson[MAXN],siz[MAXN]; void dfs1(int x,int pre){ dep[x]=dep[pre]+1;fa[x]=pre;siz[x]=1; int sz=0; for(int i=head[x];i;i=e[i].next){ int v=e[i].to; if(v==pre)continue; dfs1(v,x);siz[x]+=siz[v]; if(siz[v]>sz){sz=siz[v];hson[x]=v;} } } int top[MAXN]; void dfs2(int x,int tp){ top[x]=tp; if(hson[x])dfs2(hson[x],tp); for(int i=head[x];i;i=e[i].next){ int v=e[i].to; if(v==fa[x]||v==hson[x])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; } int rt[MAXN],num; int val[N],mx[N],mxp[N],ch[N][2]; inline int newnode(){return ++num;} inline void pushup(int cur){ int u=mx[ch[cur][0]]<mx[ch[cur][1]]; mxp[cur]=mxp[ch[cur][u]]; mx[cur]=mx[ch[cur][u]]; } void update(int x,int &cur,int l,int r,int w){ if(!cur)cur=newnode(); if(l==r){mx[cur]+=w;mxp[cur]=l;return;} int mid=(l+r)>>1; if(x<=mid)update(x,ch[cur][0],l,mid,w); else update(x,ch[cur][1],mid+1,r,w); pushup(cur); } void merge(int &u,int v,int l,int r){ if(!u||!v) {u=u+v;return;} if(l==r){ mx[u]+=mx[v]; mxp[u]=l; return; } int mid=(l+r)>>1; merge(ch[u][0],ch[v][0],l,mid); merge(ch[u][1],ch[v][1],mid+1,r); pushup(u); } int n,m,tot; int ans[MAXN]; void dfs(int x){ for(int i=head[x];i;i=e[i].next){ int v=e[i].to; if(v==fa[x])continue; dfs(v); merge(rt[x],rt[v],1,tot); } ans[x]=mxp[rt[x]]; } struct Node{ int x,y,w; }a[MAXN]; int tmp[MAXN]; int main(){ n=rd();m=rd(); int x,y,w; for(int i=1;i<n;i++){ x=rd();y=rd(); add(x,y);add(y,x); } dfs1(1,0);dfs2(1,1); for(register int i=1;i<=m;i++){ a[i].x=rd();a[i].y=rd();a[i].w=tmp[i]=rd(); } sort(tmp+1,tmp+1+m); tot=unique(tmp+1,tmp+1+m)-tmp-1; for(int i=1;i<=m;i++){ int x=a[i].x,y=a[i].y,w=lower_bound(tmp+1,tmp+1+tot,a[i].w)-tmp; update(w,rt[x],1,tot,1); update(w,rt[y],1,tot,1); int l=lca(x,y); update(w,rt[l],1,tot,-1); if(l=fa[l])update(w,rt[l],1,tot,-1); } dfs(1); for(register int i=1;i<=n;i++){ printf("%d\n",tmp[ans[i]]); } }
本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9641757.html