(ACM) How to use segment tree to count how many elements in [a,b] is smaller than a given constant? - algorithm

I am quite new to segment tree and would like to make myself busy by doing some more exercise on segment tree.
The problem's actually more ACM like and have following conditions:
There are n numbers and m operations, n,m<=10,000, each operation can be one of the following:
1. Update an interval by minus a number x, x can be different each time
2. Query an interval to find how many numbers in the interval is <= 0
Building the segment tree and updating here is obviously can be done in O(nlog n) / O(log n)
But I cannot figure out how to make a query in O(log n), can anyone give me some suggestions / hints?
Any suggestions would be helpful! Thanks!
TL;DR:
Given n numbers, and 2 type operations:
add x to all elements in [a,b], x can be different each time
Query number of elements in [a,b] is < C, C is given constant
How to make operation 1 & 2 both can be done in O(log n)?

Nice Problem:)
I think for a while but still can't work out this problem with segment tree, but I've tried using "Bucket Method" to solve this problem.
We can divide the initial n numbers into B buckets, sort the number in each buckets and maintain the total add val in each bucket. Then for each query:
"Add" update interval [a, b] with c
we only need to rebuild at most two buckets and add c to (b - a) / BUCKET_SIZE buckets
"Query" query interval [a, b] <= c
we only need to scan at most two buckets with each value one by one and quick go through (b-a) / BUCKET_SIZE buckets with binary search quickly
It should be run in O( N/BUCKET_SIZE * log(BUCKET_SIZE, 2)) for each query, which is smaller than bruteforce method( O(N)). Though it's bigger than O(logN), it may be sufficient in most cases.
Here are the test code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <ctime>
#include <cassert>
using namespace std;
struct Query {
//A a b c add c in [a, b] of arr
//Q a b c Query number of i in [a, b] which arr[i] <= c
char ty;
int a, b, c;
Query(char _ty, int _a, int _b, int _c):ty(_ty), a(_a), b(_b), c(_c){}
};
int n, m;
vector<int> arr;
vector<Query> queries;
vector<int> bruteforce() {
vector<int> ret;
vector<int> numbers = arr;
for (int i = 0; i < m; i++) {
Query q = queries[i];
if (q.ty == 'A') {
for (int i = q.a; i <= q.b; i++) {
numbers[i] += q.c;
}
ret.push_back(-1);
} else {
int tmp = 0;
for(int i = q.a; i <= q.b; i++) {
tmp += numbers[i] <= q.c;
}
ret.push_back(tmp);
}
}
return ret;
}
struct Bucket {
vector<int> numbers;
vector<int> numbers_sorted;
int add;
Bucket() {
add = 0;
numbers_sorted.clear();
numbers.clear();
}
int query(int pos) {
return numbers[pos] + add;
}
void add_pos(int pos, int val) {
numbers[pos] += val;
}
void build() {
numbers_sorted = numbers;
sort(numbers_sorted.begin(), numbers_sorted.end());
}
};
vector<int> bucket_count(int bucket_size) {
vector<int> ret;
vector<Bucket> buckets;
buckets.resize(int(n / bucket_size) + 5);
for (int i = 0; i < n; i++) {
buckets[i / bucket_size].numbers.push_back(arr[i]);
}
for (int i = 0; i <= n / bucket_size; i++) {
buckets[i].build();
}
for (int i = 0; i < m; i++) {
Query q = queries[i];
char ty = q.ty;
int a, b, c;
a = q.a, b = q.b, c = q.c;
if (ty == 'A') {
set<int> affect_buckets;
while (a < b && a % bucket_size != 0) buckets[a/ bucket_size].add_pos(a % bucket_size, c), affect_buckets.insert(a/bucket_size), a++;
while (a < b && b % bucket_size != 0) buckets[b/ bucket_size].add_pos(b % bucket_size, c), affect_buckets.insert(b/bucket_size), b--;
while (a < b) {
buckets[a/bucket_size].add += c;
a += bucket_size;
}
buckets[a/bucket_size].add_pos(a % bucket_size, c), affect_buckets.insert(a / bucket_size);
for (set<int>::iterator it = affect_buckets.begin(); it != affect_buckets.end(); it++) {
int id = *it;
buckets[id].build();
}
ret.push_back(-1);
} else {
int tmp = 0;
while (a < b && a % bucket_size != 0) tmp += (buckets[a/ bucket_size].query(a % bucket_size) <=c), a++;
while (a < b && b % bucket_size != 0) tmp += (buckets[b/ bucket_size].query(b % bucket_size) <=c), b--;
while (a < b) {
int pos = a / bucket_size;
tmp += upper_bound(buckets[pos].numbers_sorted.begin(), buckets[pos].numbers_sorted.end(), c - buckets[pos].add) - buckets[pos].numbers_sorted.begin();
a += bucket_size;
}
tmp += (buckets[a / bucket_size].query(a % bucket_size) <= c);
ret.push_back(tmp);
}
}
return ret;
}
void process(int cas) {
clock_t begin_t=clock();
vector<int> bf_ans = bruteforce();
clock_t bf_end_t =clock();
double bf_sec = ((1.0 * bf_end_t - begin_t)) / CLOCKS_PER_SEC;
//bucket_size is important
int bucket_size = 200;
vector<int> ans = bucket_count(bucket_size);
clock_t bucket_end_t =clock();
double bucket_sec = ((1.0 * bucket_end_t - bf_end_t)) / CLOCKS_PER_SEC;
bool correct = true;
for (int i = 0; i < ans.size(); i++) {
if (ans[i] != bf_ans[i]) {
cout << "query " << i + 1 << " bf = " << bf_ans[i] << " bucket = " << ans[i] << " bucket size = " << bucket_size << " " << n << " " << m << endl;
correct = false;
}
}
printf("Case #%d:%s bf_sec = %.9lf, bucket_sec = %.9lf\n", cas, correct ? "YES":"NO", bf_sec, bucket_sec);
}
void read() {
cin >> n >> m;
arr.clear();
for (int i = 0; i < n; i++) {
int val;
cin >> val;
arr.push_back(val);
}
queries.clear();
for (int i = 0; i < m; i++) {
char ty;
int a, b, c;
// a, b, c in [0, n - 1], a <= b
cin >> ty >> a >> b >> c;
queries.push_back(Query(ty, a, b, c));
}
}
void run(int cas) {
read();
process(cas);
}
int main() {
freopen("bucket.in", "r", stdin);
//freopen("bucket.out", "w", stdout);
int T;
scanf("%d", &T);
for (int cas = 1; cas <= T; cas++) {
run(cas);
}
return 0;
}
and here are the data gen code:
#coding=utf8
import random
import math
def gen_buckets(f):
t = random.randint(10, 20)
print >> f, t
nlimit = 100000
mlimit = 10000
limit = 100000
for i in xrange(t):
n = random.randint(1, nlimit)
m = random.randint(1, mlimit)
print >> f, n, m
for i in xrange(n):
val = random.randint(1, limit)
print >> f, val ,
print >> f
for i in xrange(m):
ty = random.randint(1, 2)
a = random.randint(0, n - 1)
b = random.randint(a, n - 1)
#a = 0
#b = n - 1
c = random.randint(-limit, limit)
print >> f, 'A' if ty == 1 else 'Q', a, b, c
f = open("bucket.in", "w")
gen_buckets(f)

Try applying a Binary Index Trees (BIT) instead of a segmented tree. Here's the link to the tutorial

Related

Convert a number m to n using minimum number of given operations

Question:
Given 2 integers N and M. Convert a number N to M using minimum number of given operations.
The operations are:
Square N (N = N^2)
Divide N by a prime integer P if N is divisible by P (N = N / P and N % P == 0)
Contrants:
N, M <= 10^9
Example:
N = 12, M = 18
The minimum operations are:
N /= 2 -> N = 6
N = N^2 -> N = 36
N /= 2 -> N = 18
My take:
I'm trying to use BFS to solve this problem. For each number, the available edges to other numberers are the operations. But it got Time Limit Exceeded. Is there any better way to solve this?
Here is my BFS code:
queue<pair<int,int> > q;
vector<long long> pr;
ll m,n;
bool prime[MAXN+1];
void solve()
{
while (!q.empty())
{
pii x=q.front();
q.pop();
if (x.first==m)
{
cout << x.second;
return;
}
if (x.first==1) continue;
for(ll k:pr)
{
if (k>x.first) break;
if (x.first%k==0) q.push({x.first/k,x.second+1});
}
q.push({x.first*x.first,x.second+1});
}
}
The algorithm uses the decomposition on N and M in prime factors, keeping trace of the corresponding exponents.
If M has a prime factor that N does not have, there is no solution (the code returns -1).
If N has some prime factors that M doesn't have, then the first step is to divide N by these primes.
The corresponding number of operations is the sum of the corresponding exponents.
At this stage, we get two arrays A and B corresponding to the exponents of the common prime factors, for N and M.
It is worth noting that at this stage, the values of the primes involved is not relevant anymore, only the exponents matter.
Then one must determine the minimum number of squares (= multiplications by 2 of the exponents).
The is the smallest k such that A[i] >= 2^k B[i] for all indices i.
The number of multiplications is added to the number of operations only once, as all exponents are multiplied by 2 at the same time.
Last step is to determine, for each pair (a, b) = (A[i], B[i]), the number of subtractions needed to go from a to b, while implementing exactly k multiplications by 2. This is performed with the following rules:
- if (k == 0) f(a, b, k) = a-b
- Else:
- if ((a-1)*2^k >= b: f(a, b, k) = 1 + f(a-1, b, k)
- else: f(a, b, k) = f(2*a, b, k-1)
The complexity is dominated by the decomposition in primes factors: O(sqrt(n))
Code:
This code is rather long, but a great part consists if helper routines needed for debugging and analysis.
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
void print (const std::vector<int> &v, const std::string s = "") {
std::cout << s;
for (auto &x: v) {
std::cout << x << " ";
}
std::cout << std::endl;
}
void print_decomp (int n, const std::vector<int> &primes, const std::vector<int> &mult) {
std::cout << n << " = ";
int k = primes.size();
for (int i = 0; i < k; ++i) {
std::cout << primes[i];
if (mult[i] > 1) std::cout << "^" << mult[i];
std::cout << " ";
}
std::cout << "\n";
}
void prime_decomp (int nn, std::vector<int> &primes, std::vector<int> &mult) {
int n = nn;
if (n <= 1) return;
if (n % 2 == 0) {
primes.push_back(2);
int cpt = 1;
n/= 2;
while (n%2 == 0) {n /= 2; cpt++;}
mult.push_back (cpt);
}
int max_prime = sqrt(n);
int p = 3;
while (p <= max_prime) {
if (n % p == 0) {
primes.push_back(p);
int cpt = 1;
n/= p;
while (n%p == 0) {n /= p; cpt++;}
mult.push_back (cpt);
max_prime = sqrt(n);
}
p += 2;
}
if (n != 1) {
primes.push_back(n);
mult.push_back (1);
}
print_decomp (nn, primes, mult);
}
// Determine the number of subtractions to go from a to b, with exactly k multiplications by 2
int n_sub (int a, int b, int k, int power2) {
if (k == 0){
if (b > a) exit(1);
return a - b;
}
//if (a == 1) return n_sub (2*a, b, k-1, power2/2);
if ((a-1)*power2 >= b) {
return 1 + n_sub(a-1, b, k, power2);
} else {
return n_sub (2*a, b, k-1, power2/2);
}
return 0;
}
// A return of -1 means no possibility
int n_operations (int N, int M) {
int count = 0;
if (N == M) return 0;
if (N == 1) return -1;
std::vector<int> primes_N, primes_M, expon_N, expon_M;
// Prime decomposition
prime_decomp(N, primes_N, expon_N);
prime_decomp (M, primes_M, expon_M);
// Compare decomposition, check if a solution can exist, set up two exponent arrays
std::vector<int> A, B;
int index_A = 0, index_B = 0;
int nA = primes_N.size();
int nB = primes_M.size();
while (true) {
if ((index_A == nA) && (index_B == nB)) {
break;
}
if ((index_A < nA) && (index_B < nB)) {
if (primes_N[index_A] == primes_M[index_B]) {
A.push_back(expon_N[index_A]);
B.push_back(expon_M[index_B]);
index_A++; index_B++;
continue;
}
if (primes_N[index_A] < primes_M[index_B]) {
count += expon_N[index_A];
index_A++;
continue;
}
return -1; // M has a prime that N doesn't have: impossibility to go to M
}
if (index_B != nB) { // impossibility
return -1;
}
for (int i = index_A; i < nA; ++i) {
count += expon_N[i]; // suppression of primes in N not in M
}
break;
}
std::cout << "1st step, count = " << count << "\n";
print (A, "exponents of N: ");
print (B, "exponents of M: ");
// Determination of the number of multiplications by two of the exponents (= number of squares)
int n = A.size();
int n_mult2 = 0;
int power2 = 1;
for (int i = 0; i < n; ++i) {
while (power2*A[i] < B[i]) {
power2 *= 2;
n_mult2++;
}
}
count += n_mult2;
std::cout << "number of squares = " << n_mult2 << " -> " << power2 << "\n";
// For each pair of exponent, determine the number of subtractions,
// with a fixed number of multiplication by 2
for (int i = 0; i < n; ++i) {
count += n_sub (A[i], B[i], n_mult2, power2);
}
return count;
}
int main() {
int N, M;
std::cin >> N >> M;
auto ans = n_operations (N, M);
std::cout << ans << "\n";
return 0;
}

Queries on permutation 1...N

So we are given a permutation of the numers {1... N}.
We are given an integer k and then k queries of this type:
q(x,y,l,r) - count numbers between position X and Y in the permutation, which are >=l and <=r.
For example:
N - 7: (1 6 3 5 7 4 2)
q(1,4,2,7) -> 3 numbers ( 6, 3 and 5 , since 2<=6<=7 , 2<=3<=7 and 2<=5<=7)
So my attempt was to store the permutation and and position array (too have fast acces to the position of each number)
Then i check which interval is smaller [x,y] or [l,r] and iterate through the smaller.
The answers i get are correct, but i get 0 points, since my solution it's too slow.
Any tips how to make this queries as fast as possible for big N?
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int q;
cin >> q;
int* perm = new int[n+1];
int* pos = new int[n+1];
for (int i = 1; i <= n; i++)
{
int num;
cin >> num;
perm[i] = num;
pos[num] = i;
}
for (int i = 0; i < q; i++)
{
int x, y, l, r;
cin >> x >>y>> l>> r;
int count = 0;
if (y - x < r - l)
{
for (int i = x; i <= y; i++)
{
if (perm[i] >= l && perm[i] <= r)
count++;
}
cout << count << endl;
}
else
{
int count = 0;
for (int i = l; i <= r; i++)
{
if (pos[i] >= x && pos[i] <= y)
count++;
}
cout << count << endl;
}
}
}

Mapping a large number to a unique number using MOD operation

Let the Roots of a first degree polynomial( Q(x) ) be x0 = -b/a. Since the range of the variable a and b is large, x0 can be large as well for it to be stored in a variable(x0).
so, it is converted to some unique number using some operation with mod
int x0 = mul(mod - b, rev(a));
problem link: hackerank problem
Can someone please explain how this line of code works and the math behind this operation?
the whole code-
#include <bits/stdc++.h>
using namespace std;
#define forn(i,n) for (int i = 0; i < int(n); ++i)
typedef long long ll;
const int inf = int(1e9) + int(1e5);
const ll infl = ll(2e18) + ll(1e10);
const int mod = 1e9 + 7;
int udd(int &a, int b) {
a += b;
if (a >= mod)
a -= mod;
return a;
}
int add(int a, int b) {
return udd(a, b);
}
int mul(ll a, ll b) {
return a * b % mod;
}
//============didnt understand this step
int bin(int a, int d) {
int b = 1;
while (d) {
if (d & 1)
b = mul(b, a);
d >>= 1;
a = mul(a, a);
}
return b;
}
int rev(int a) {
assert(a != 0);
return bin(a, mod - 2);
}
const int maxn = 100100;
int px[maxn];
int c[maxn];
struct Fenwick {
int a[maxn];
int t[maxn];
void set(int pos, int val) {
int delta = add(val, mod - a[pos]);
a[pos] = val;
delta = mul(delta, px[pos]);
for (int i = pos; i < maxn; i |= i + 1) {
udd(t[i], delta);
}
}
int get(int r) {
int res = 0;
for (int i = r - 1; i >= 0; i = (i & (i + 1)) - 1)
udd(res, t[i]);
return res;
}
int get(int l, int r) {
return add(get(r), mod - get(l));
}
} fw;
int main() {
#ifdef LOCAL
assert(freopen("test.in", "r", stdin));
#endif
int n, a, b, q;
cin >> n >> a >> b >> q;
//========what does this line do?
int x0 = mul(mod - b, rev(a));
px[0] = 1;
for (int i = 1; i < n; ++i)
px[i] = mul(px[i - 1], x0);
forn (i, n) {
cin >> c[i];
fw.set(i, c[i]);
}
forn (i, q) {
int t, a, b;
cin >> t >> a >> b;
if (t == 1) {
fw.set(a, b);
} else {
++b;
int s = fw.get(a, b);
if (x0 == 0)
s = fw.a[a];
cout << (s == 0 ? "Yes" : "No") << '\n';
}
}
}
bin is the halving-and-squaring implementation for the (in this case modular) power function a^d % mod, so that the modular inverse in rev can be computed via the little theorem of Fermat.

Algorithm. How to find longest subsequence of integers in an array such that gcd of any two consecutive number in the sequence is greather than 1?

Given`en an array of integers. We have to find the length of the longest subsequence of integers such that gcd of any two consecutive elements in the sequence is greater than 1.
for ex: if array = [12, 8, 2, 3, 6, 9]
then one such subsequence can be = {12, 8, 2, 6, 9}
other one can be= {12, 3, 6, 9}
I tried to solve this problem by dynamic programming. Assume that maxCount is the array such that maxCount[i] will have the length of such longest subsequence
ending at index i.
`maxCount[0]=1 ;
for(i=1; i<N; i++)
{
max = 1 ;
for(j=i-1; j>=0; j--)
{
if(gcd(arr[i], arr[j]) > 1)
{
temp = maxCount[j] + 1 ;
if(temp > max)
max = temp ;
}
}
maxCount[i]=max;
}``
max = 0;
for(i=0; i<N; i++)
{
if(maxCount[i] > max)
max = maxCount[i] ;
}
cout<<max<<endl ;
`
But, this approach is getting timeout. As its time complexity is O(N^2). Can we improve the time complexity?
The condition "gcd is greater than 1" means that numbers have at least one common divisor. So, let dp[i] equals to the length of longest sequence finishing on a number divisible by i.
int n;
cin >> n;
const int MAX_NUM = 100 * 1000;
static int dp[MAX_NUM];
for(int i = 0; i < n; ++i)
{
int x;
cin >> x;
int cur = 1;
vector<int> d;
for(int i = 2; i * i <= x; ++i)
{
if(x % i == 0)
{
cur = max(cur, dp[i] + 1);
cur = max(cur, dp[x / i] + 1);
d.push_back(i);
d.push_back(x / i);
}
}
if(x > 1)
{
cur = max(cur, dp[x] + 1);
d.push_back(x);
}
for(int j : d)
{
dp[j] = cur;
}
}
cout << *max_element(dp, dp + MAX_NUM) << endl;
This solution has O(N * sqrt(MAX_NUM)) complexity. Actually you can calculate dp values only for prime numbers. To implement this you should be able to get prime factorization in less than O(N^0.5) time (this method, for example). That optimization should cast complexity to O(N * factorization + Nlog(N)). As memory optimization, you can replace dp array with map or unordered_map.
GCD takes log m time, where m is the maximum number in the array. Therefore, using a Segment Tree and binary search, one can reduce the time complexity to O(n log (m² * n)) (with O(n log m) preprocessing). This list details other data structures that can be used for RMQ-type queries and to reduce the complexity further.
Here is one possible implementation of this:
#include <bits/stdc++.h>
using namespace std;
struct SegTree {
using ftype = function<int(int, int)>;
vector<int> vec;
int l, og, dummy;
ftype f;
template<typename T> SegTree(const vector<T> &v, const T &x, const ftype &func) : og(v.size()), f(func), l(1), dummy(x) {
assert(og >= 1);
while (l < og) l *= 2;
vec = vector<int>(l*2);
for (int i = l; i < l+og; i++) vec[i] = v[i-l];
for (int i = l+og; i < 2*l; i++) vec[i] = dummy;
for (int i = l-1; i >= 1; i--) {
if (vec[2*i] == dummy && vec[2*i+1] == dummy) vec[i] = dummy;
else if (vec[2*i] == dummy) vec[i] = vec[2*i+1];
else if (vec[2*i+1] == dummy) vec[i] = vec[2*i];
else vec[i] = f(vec[2*i], vec[2*i+1]);
}
}
SegTree() {}
void valid(int x) {assert(x >= 0 && x < og);}
int get(int a, int b) {
valid(a); valid(b); assert(b >= a);
a += l; b += l;
int s = vec[a];
a++;
while (a <= b) {
if (a % 2 == 1) {
if (vec[a] != dummy) s = f(s, vec[a]);
a++;
}
if (b % 2 == 0) {
if (vec[b] != dummy) s = f(s, vec[b]);
b--;
}
a /= 2; b /= 2;
}
return s;
}
void add(int x, int c) {
valid(x);
x += l;
vec[x] += c;
for (x /= 2; x >= 1; x /= 2) {
if (vec[2*x] == dummy && vec[2*x+1] == dummy) vec[x] = dummy;
else if (vec[2*x] == dummy) vec[x] = vec[2*x+1];
else if (vec[2*x+1] == dummy) vec[x] = vec[2*x];
else vec[x] = f(vec[2*x], vec[2*x+1]);
}
}
void update(int x, int c) {add(x, c-vec[x+l]);}
};
// Constructor (where val is something that an element in the array is
// guaranteed to never reach):
// SegTree st(vec, val, func);
// finds longest subsequence where GCD is greater than 1
int longest(const vector<int> &vec) {
int l = vec.size();
SegTree st(vec, -1, [](int a, int b){return __gcd(a, b);});
// checks if a certain length is valid in O(n log (m² * n)) time
auto valid = [&](int n) -> bool {
for (int i = 0; i <= l-n; i++) {
if (st.get(i, i+n-1) != 1) {
return true;
}
}
return false;
};
int length = 0;
// do a "binary search" on the best possible length
for (int i = l; i >= 1; i /= 2) {
while (length+i <= l && valid(length+i)) {
length += i;
}
}
return length;
}

Hacker rank Similar Pairs

I am trying to solve hacker rank similar pairs https://www.hackerrank.com/contests/101hack/challenges/similarpair problem. I cant figure out why its failing for large test cases. I am using segment trees to solve this problem in nlogn time. You can find my code below.
#include<iostream>
#include<vector>
using namespace std;
vector<int> graph[110001];
int T, ST[100001*4] = {0}, N, deg[100001] = {0};
void update(int node, int b, int e, int idx, int val) {
if(b > node || e < node) return;
if(b == e) {
ST[idx] += val;
return;
}
update(node, b, (b + e)/2, 2 * idx, val);
update(node, (b + e)/2 + 1, e, 2 * idx + 1, val);
ST[idx] = ST[2 * idx] + ST[2 * idx + 1];
}
long Query(int l, int r, int b, int e, int idx) {
if( l > e || r < b) return 0;
if(l <= b && r >= e) return ST[idx];
return Query(l, r, b, (b + e)/2, 2 * idx) + Query(l, r, (b + e)/2 + 1, e, 2 * idx + 1);
}
long long SimilarPairs(int node) {
int l = max(1, node - T), r = min(N, node + T);
long res = 0;
res = Query(l, r, 1, N, 1);
update(node, 1, N, 1, 1);
for(int i = 0; i < graph[node].size(); i++) {
res += SimilarPairs(graph[node][i]);
}
update(node, 1, N, 1, -1);
return res;
}
int main() {
long x, y, root, result, start;
cin >> N >> T;
for(int i = 0; i < N - 1; i++) {
cin >> x >> y;
graph[x].push_back(y);
deg[y]++;
}
for(int i = 1; i <= N; i++) if(!deg[i]) root = i;
result = SimilarPairs(root);
cout << result << endl;
cin.get();
return 0;
}
I get what you were doing. The problem is that you were missing some long longs. long is the same as an int (on 32 bits), so you must use long long everywhere, since the result does not necessarily fit in a 32 bit int.
This gets AC:
#include<iostream>
#include<vector>
using namespace std;
vector<int> graph[110001];
int T, N, deg[100001] = {0};
long long ST[100001*4] = {0};
void update(int node, int b, int e, int idx, int val) {
if(b > node || e < node) return;
if(b == e) {
ST[idx] += val;
return;
}
int m = (b + e) >> 1;
int q = idx << 1;
update(node, b, m, q, val);
update(node, m + 1, e, q + 1, val);
ST[idx] = ST[q] + ST[q+1];
}
long long Query(int l, int r, int b, int e, int idx) {
if( l > e || r < b) return 0;
if(l <= b && r >= e) return ST[idx];
int m = (b + e) >> 1;
int q = idx << 1;
return Query(l, r, b, m, q) + Query(l, r, m + 1, e, q + 1);
}
long long SimilarPairs(int node) {
int l = max(1, node - T), r = min(N, node + T);
long long res = 0;
res = Query(l, r, 1, N, 1);
update(node, 1, N, 1, 1);
for(int i = 0; i < graph[node].size(); i++) {
res += SimilarPairs(graph[node][i]);
}
update(node, 1, N, 1, -1);
return res;
}
int main() {
long x, y, root, start;
cin >> N >> T;
for(int i = 0; i < N - 1; i++) {
cin >> x >> y;
graph[x].push_back(y);
deg[y]++;
}
for(int i = 1; i <= N; i++) if(!deg[i]) root = i;
long long result = SimilarPairs(root);
cout << result << endl;
cin.get();
return 0;
}

Resources