和poj1747相比起来,只不过是限制条件多了一维。
而多了这一维,所以需要用树状数组来维护,从而快速得到答案。
因为没注意传进树状数组函数的参数可能是<=0的,导致超时了好久。
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <bitset>
#include <algorithm>
#include <iostream>
#include <string>
#include <functional>
const int INF = << ;
typedef __int64 LL;
/**/
const int N = + ; int n, L, W;
struct Edge
{
int to, dis, next;
}g[N*];
struct Node
{
int l, w;
bool operator<(const Node&rhs)const
{
return w < rhs.w;
}
}a[N];
int head[N], e;
int tree[N];
int size[N], p, total, mins, root;
bool vis[N];
LL ans;
int maxL;
int lowbit(int x)
{
return x &(-x);
} //树状数组如果pos<=0,那么会死循环, 卡这里超时了好久。
void modify(int pos, int val)
{
pos += ;
while (pos <= maxL+)
{
tree[pos] += val;
pos += lowbit(pos);
}
}
int getSum(int pos)
{
pos += ;
if (pos <= ) return ;
int ret = ;
while (pos > )
{
ret += tree[pos];
pos -= lowbit(pos);
}
return ret;
} void addEdge(int u, int v, int dis)
{
g[e].to = v;
g[e].dis = dis;
g[e].next = head[u];
head[u] = e++;
} void getRoot(int u, int fa)
{
int maxs = ;
size[u] = ;
for (int i = head[u];i != -;i = g[i].next)
{
int v = g[i].to;
if (v == fa || vis[v]) continue;
getRoot(v, u);
size[u] += size[v];
maxs = std::max(maxs, size[v]);
}
maxs = std::max(maxs, total - size[u]);
if (mins > maxs)
{
mins = maxs;
root = u;
}
}
void getA(int u, int fa, int l, int w)
{
a[p].l = l;
a[p++].w = w;
maxL = std::max(maxL, l);
for (int i = head[u];i != -;i = g[i].next)
{
int v = g[i].to;
if (v == fa || vis[v]) continue;
getA(v, u, l + , w + g[i].dis);
}
} LL counts(int u, int ll, int ww)
{
p = ;
maxL = ;
getA(u, -, ll, ww);
std::sort(a, a + p);
int l = , r = p - ;
LL ret = ;
while (l < r &&a[l].w + a[r].w>W)
r--;
if (l < r)
{
for (int i = l+;i <= r;++i)
modify(a[i].l,);
while (l < r)
{
if (a[l].w + a[r].w <= W)
{
ret += getSum(std::min(L - a[l].l,maxL));
l++;
modify(a[l].l,-);
}
else
{
modify(a[r].l,-);
r--;
}
}
}
return ret;
} void go(int u)
{
vis[u] = true;
ans += counts(u, , );
for (int i = head[u];i != -;i = g[i].next)
{
int v = g[i].to;
if (vis[v]) continue;
ans -= counts(v, , g[i].dis);
mins = INF;
total = size[v];
getRoot(v, -);
go(root);
}
}
int main()
{
scanf("%d%d%d", &n, &L, &W); int u, v, dis;
memset(head, -, sizeof(head));
for (int i = ;i < n;++i)
{
u = i + ;
scanf("%d%d", &v, &dis);
addEdge(u, v, dis);
addEdge(v, u, dis);
}
mins = INF;
total = n;
getRoot(, -);
go(root);
printf("%I64d\n", ans); return ;
}