題解 P3066 【[USACO12DEC]Running Away From the Barn G】
阿新 • • 發佈:2020-09-02
原文連結
題意很清晰,我們可以用字首和轉化一下,設\(u\)到根的距離為\(dis[u]\),則在\(u\)的子樹中滿足到\(u\)的距離不大於\(t\)的點\(v\)滿足
\[dis[v]-dis[u]\leq t \]
即
\[dis[u]+t\geq dis[v] \]
我們先跑一邊\(dfs\),每個點的子樹就對應一段區間,然後問題就轉化成了:求一段區間內小於等於某個數的值有幾個,裸的主席樹。
然後上板子即可,但細節有點多。
\(Code\)
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int maxn=2e5+5; struct edge { int v,nxt; ll w; edge(int v=0,ll w=0,int nxt=0) :v(v),w(w),nxt(nxt){} }e[maxn<<1]; int lc[maxn<<5],rc[maxn<<5],sum[maxn<<5]; int rt[maxn],tot; int head[maxn],kt,dfn[maxn],siz[maxn],n,cnt,m,id[maxn]; ll dis[maxn],b[maxn],t; template<typename T> inline void read(T &x) { char c;int f=1; while(!isdigit(c=getchar())) (c=='-')&&(f=-1); x=c^48; while(isdigit(c=getchar())) x=x*10+(c^48); x*=f; } inline void add(int u,int v,ll w) { e[++kt] = edge(v, w, head[u]); head[u] = kt; } void dfs(int u,int fa,ll ds) { dis[u] = ds;siz[u] = 1; dfn[u] = ++cnt;id[cnt]=u; for (int i = head[u];i;i=e[i].nxt) if(e[i].v!=fa) { dfs(e[i].v, u, ds + e[i].w); siz[u] += siz[e[i].v]; } } void build(int &u,int l,int r) { u=++tot; if(l==r) return; int mid=(l+r)>>1; build(lc[u],l,mid);build(rc[u],mid+1,r); } void insert(int &u,int pre,int l,int r,int x) { u=++tot;lc[u]=lc[pre];rc[u]=rc[pre];sum[u]=sum[pre]+1; if(l==r) return; int mid=(l+r)>>1; if(x<=mid) insert(lc[u],lc[pre],l,mid,x); else insert(rc[u],rc[pre],mid+1,r,x); } int query(int u,int v,int l,int r,int x,int y) { if(r<x||l>y) return 0; if(x<=l&&r<=y) return sum[v]-sum[u]; int mid=(l+r)>>1; return query(rc[u],rc[v],mid+1,r,x,y)+query(lc[u],lc[v],l,mid,x,y); } int main() { int u; ll w; read(n);read(t); for (int i=2;i<=n;++i) { read(u);read(w); add(i,u,w);add(u,i,w); } dfs(1,0,0); for(int i=1;i<=n;++i) b[i]=dis[i]; sort(b+1,b+n+1);b[n+1]=1e18; m=unique(b+1,b+n+2)-b-1; build(rt[0],1,m); for(int i=1;i<=n;++i) insert(rt[i],rt[i-1],1,m,lower_bound(b+1,b+m+1,dis[id[i]])-b); for(int i=1;i<=n;++i) { int x=lower_bound(b+1,b+m+1,dis[i])-b-1,y=lower_bound(b+1,b+m+1,dis[i]+t)-b-1; if(b[x+1]==dis[i]) ++x;if(b[y+1]==dis[i]+t) ++y; if(y==m-1) printf("%d\n",siz[i]); else printf("%d\n",query(rt[dfn[i]-1],rt[dfn[i]+siz[i]-1],1,m,x,y)); } return 0; }