P3066 [USACO12DEC] Running Away From the Barn G
P3066 [USACO12DEC] Running Away From the Barn G
题目描述
给定一颗
再给出一个参数
输入格式
输入的第一行是两个整数,分别表示节点数
第
输出格式
输出
数据规模与约定
对于全部的测试点,保证:
, 。 , 。
Solution:
线段树合并板子捏。
我们先对这整颗树求出每个点到根的距离
然后我们发现每个点都开一颗权值线段树然后遍历子树更新肯定是不行的,所以我们需要线段树合并。
然后这题就做完了
然后这题貌似还有个弱化版本this
Code:
#include<bits/stdc++.h> #define int long long const int N=2e5+5; const int inf=1e17; using namespace std; struct Segment_Tree{ int cnt,rt[N]; struct Tree{ int ls,rs,cnt; }t[N*40]; void pushup(int x) { t[x].cnt=t[t[x].ls].cnt+t[t[x].rs].cnt; } void insert(int &x,int l,int r,int pos) { if(!x)x=++cnt; t[x].cnt++; if(l==r)return; int mid=l+r>>1; if(pos<=mid)insert(t[x].ls,l,mid,pos); if(mid<pos) insert(t[x].rs,mid+1,r,pos); } int merge(int x,int y,int l,int r) { if(!x||!y)return x|y; if(l==r) { t[x].cnt+=t[y].cnt; return x; } int mid=l+r>>1; t[x].ls=merge(t[x].ls,t[y].ls,l,mid); t[x].rs=merge(t[x].rs,t[y].rs,mid+1,r); pushup(x); return x; } int query(int x,int l,int r,int L,int R) { if(L<=l&&r<=R) { //cout<<"query:"<<l<<" "<<r<<"="<<t[x].cnt<<"\n"; return t[x].cnt; } int mid=l+r>>1,res=0; if(L<=mid)res+=query(t[x].ls,l,mid,L,R); if(mid<R)res+=query(t[x].rs,mid+1,r,L,R); return res; } }T; int n,m; vector<tuple<int,int> > E[N]; int dis[N],a[N],b[N],ans[N]; void dfs(int x) { for(auto [y,w] :E[x]) { dis[y]=dis[x]+w; dfs(y); } } void calc(int x) { T.insert(T.rt[x],1,n,dis[x]); //cout<<"upd:"<<T.rt[x]<<" "<<dis[x]<<"\n"; for(auto [y,w] : E[x]) { calc(y); //cout<<"merge:"<<x<<" "<<y<<"="<<T.rt[x]<<" "<<T.rt[y]<<"\n"; T.rt[x]=T.merge(T.rt[x],T.rt[y],1,n); } ans[x]=T.query(T.rt[x],1,n,1,a[x]); //cout<<"ans : "<<x<<" : "<<dis[x]<<"="<<ans[x]<<"\n"; } void work() { cin>>n>>m; for(int i=1,x,y;i<n;i++) { scanf("%lld%lld",&x,&y); E[x].emplace_back(i+1,y); } dfs(1); for(int i=1;i<=n;i++)b[i]=dis[i]; b[n+1]=inf; sort(b+1,b+2+n); int tot=unique(b+1,b+2+n)-(b+1); for(int i=1;i<=n;i++) { a[i]=dis[i]+m; int k=lower_bound(b+1,b+1+tot,dis[i])-b-1,kk=lower_bound(b+1,b+1+tot,a[i])-b-1; dis[i]= dis[i]==b[k+1] ? k+1 : k; a[i]= a[i]==b[kk+1] ? kk+1 : kk; } calc(1); for(int i=1;i<=n;i++)printf("%lld\n",ans[i]); } #undef int int main() { //freopen("run.in","r",stdin); //freopen("run.out","w",stdout); work(); return 0; }