CF793B Alyona and a tree

Captain_Paul

2018-09-21 21:43:23

Personal

题意:如果$y$在$x$的子树中且$dist(x,y)<=a_y$,则$x$控制$y$ 给定一棵树,求每个点控制了几个点 ------------ 二分+树上差分+前缀和 用一个栈保存$dfs$序 对于每个点二分它的祖先 这个祖先是满足$sum[x]+w[k]>=sum[k]$的最靠上的$x$ 然后$--ans[x-1],++ans[top-1]$做差分 $ans[k]=sigma(ans[v])$,相当于前缀和与差分的转化 ``` #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #define reg register using namespace std; typedef long long ll; const int N=2e5+5; struct node { int to,nxt,dis; }edge[N]; int n,num,head[N],w[N],ans[N],stack[N],top; ll sum[N]; inline int read() { int x=0,w=1; char c=getchar(); while (!isdigit(c)&&c!='-') c=getchar(); if (c=='-') c=getchar(),w=-1; while (isdigit(c)) { x=(x<<1)+(x<<3)+c-'0'; c=getchar(); } return x*w; } inline void add_edge(int from,int to,int dis) { edge[++num]=(node){to,head[from],dis}; head[from]=num; } void dfs(int k) { stack[++top]=k; int l=0,r=top,pos=0; while (l<=r) { int mid=(l+r)>>1; if (sum[stack[mid]]>=sum[k]-w[k]) pos=mid,r=mid-1; else l=mid+1; } ++ans[stack[top-1]]; --ans[stack[pos-1]]; for (reg int i=head[k];i;i=edge[i].nxt) { int v=edge[i].to,d=edge[i].dis; sum[v]=sum[k]+d; dfs(v); ans[k]+=ans[v]; } --top; } int main() { n=read(); for (reg int i=1;i<=n;w[i++]=read()); for (reg int i=2;i<=n;i++) { int x=read(),y=read(); add_edge(x,i,y); } dfs(1); for (reg int i=1;i<=n;i++) printf("%d ",ans[i]); return 0; } ```