It's milking time at Farmer John's farm, but the cows have all run away! Farmer John needs to round them all up, and needs your help in the search.c++
FJ's farm is a series of N (1 <= N <= 200,000) pastures numbered 1...N connected by N - 1 bidirectional paths. The barn is located at pasture 1, and it is possible to reach any pasture from the barn.ide
FJ's cows were in their pastures this morning, but who knows where they ran to by now. FJ does know that the cows only run away from the barn, and they are too lazy to run a distance of more than L. For every pasture, FJ wants to know how many different pastures cows starting in that pasture could have ended up in.優化
Note: 64-bit integers (int64 in Pascal, long long in C/C++ and long in Java) are needed to store the distance values.this
給出以1號點爲根的一棵有根樹,問每一個點的子樹中與它距離小於等於l的點有多少個。spa
輸入格式:code
Line 1: 2 integers, N and L (1 <= N <= 200,000, 1 <= L <= 10^18)get
Lines 2..N: The ith line contains two integers p_i and l_i. p_i (1 <= p_i < i) is the first pasture on the shortest path between pasture i and the barn, and l_i (1 <= l_i <= 10^12) is the length of that path.it
輸出格式:io
輸入樣例#1:ast
4 5
1 4
2 3
1 5
輸出樣例#1:
3
2
1
1
Cows from pasture 1 can hide at pastures 1, 2, and 4.
Cows from pasture 2 can hide at pastures 2 and 3.
Pasture 3 and 4 are as far from the barn as possible, and the cows can hide there.
這道題作法也是千千萬萬...倍增+差分/左偏樹/主席樹/...
蒟蒻我寫的主席樹
左偏樹只寫過一道題,因此對這道題思路不是很熟,稍微講一下倍增+差分的思路吧,咱們要找到一個點的子樹中距離小於等於L的節點的個數,最樸素的作法就是暴力查找,找到一個打標記,可是這樣的優化空間很大,尋找咱們能夠用倍增優化,標記能夠差分,時間複雜度\(O(nlogn)\)
下面是主席樹的思路,咱們要尋找一個節點\(u\)子樹中距離小於等於L的節點\(v\)的個數,即須要知足這樣的條件:\(dis[v]-dis[u]<=L\to dis[u]>=dis[v]+L\)
問題就轉化成了求子樹內小於一個值的個數,主席樹啊
對權值建樹....
注意:dis[v]+L不必定在原序列中出現過,因此咱們用upper_bound,找的時候就變成嚴格<才統計答案,最後爲了必定能找到,咱們在序列的末尾加一個inf
#include<bits/stdc++.h> #define mid ((l+r)>>1) #define in(i) (i=read()) #define lol long long using namespace std; const lol N=2e5+10,inf=2e15; lol read() { lol ans=0,f=1; char i=getchar(); while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();} while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0',i=getchar(); return ans*f; } lol n,m,cur,tot,dfscnt,L; lol head[N],nex[N<<1],to[N<<1],w[N<<1]; lol a[N],b[N],inc[N],ouc[N],rt[N]; struct Chair_Tree { lol l,r,v; }t[N<<5]; void add(lol a,lol b,lol c) { to[++cur]=b,nex[cur]=head[a],w[cur]=c,head[a]=cur; to[++cur]=a,nex[cur]=head[b],w[cur]=c,head[b]=cur; } void insert(lol &u,lol l,lol r,lol pre,lol p) { t[u=++tot]=t[pre], t[u].v++; if(l==r) return; if(p<=mid) insert(t[u].l,l,mid,t[pre].l,p); else insert(t[u].r,mid+1,r,t[pre].r,p); } lol query(lol u,lol v,lol l,lol r,lol k) { if(r<k) return t[v].v-t[u].v; if(l>=k) return 0; if(k<=mid) return query(t[u].l,t[v].l,l,mid,k); else return query(t[u].r,t[v].r,mid+1,r,k)+t[t[v].l].v-t[t[u].l].v; } void init(lol u,lol fa,lol now) { inc[u]=++dfscnt, a[++m]=b[m]=now; for (lol i=head[u];i;i=nex[i]) { if(to[i]==fa) continue; init(to[i],u,now+w[i]); }ouc[u]=dfscnt; } int main() { in(n), in(L); for (lol i=2,f,c;i<=n;i++) in(f), in(c), add(i,f,c); init(1,0,0); sort(b+1,b+1+m); m=unique(b+1,b+1+m)-b-1; for (lol i=1;i<=n;i++) { lol p=lower_bound(b+1,b+1+m,a[i])-b; insert(rt[i],1,m,rt[i-1],p); } b[m+1]=inf; for (lol i=1,ans;i<=n;i++) { lol k=upper_bound(b+1,b+2+m,a[inc[i]]+L)-b; ans=query(rt[inc[i]-1],rt[ouc[i]],1,m,k); printf("%lld\n",ans); } }