题面

题解

感觉和\(CDQ\)分治一样套路啊

首先,构建出点分树

对于每一层分治重心,求出它到子树中任意点的距离

然后\(two-pointers\)计算满足小于等于\(K\)的点对数目,加入答案

但是可能会算重,那么就减去子树内两两点之间的贡献即可。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define clear(x, y) memset(x, y, sizeof(x)); namespace IO
{
const int BUFSIZE = 1 << 20;
char ibuf[BUFSIZE], *is = ibuf, *it = ibuf;
inline char getchar() { if (is == it) it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin); return *is++; }
} inline int read()
{
int data = 0, w = 1;
char ch = IO::getchar();
while(ch != '-' && (ch < '0' || ch > '9')) ch = IO::getchar();
if(ch == '-') w = -1, ch = IO::getchar();
while(ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = IO::getchar();
return data*w;
} const int maxn(40010);
struct edge { int next, to, dis; } e[maxn << 1];
int head[maxn], e_num, n, Size, Max, root, stk[maxn], dep[maxn], top, size[maxn], K, ans, vis[maxn];
inline void add_edge(int from, int to, int dis) { e[++e_num] = (edge) {head[from], to, dis}; head[from] = e_num; } void GetRoot(int x, int fa)
{
size[x] = 1; int max = 0;
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(to == fa || vis[to]) continue;
GetRoot(to, x); size[x] += size[to]; max = std::max(max, size[to]);
}
max = std::max(max, Size - size[x]);
if(max < Max) Max = max, root = x;
} void GetDep(int x, int fa)
{
stk[++top] = dep[x];
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(to == fa || vis[to]) continue;
dep[to] = dep[x] + e[i].dis; GetDep(to, x);
}
} int Calc(int x, int pre)
{
top = 0; dep[x] = pre; GetDep(x, 0); std::sort(stk + 1, stk + top + 1);
int l = 1, r = top, sum = 0;
while(l < r) { if(stk[l] + stk[r] <= K) sum += r - l, ++l; else --r; }
return sum;
} void Solve(int x)
{
ans += Calc(x, 0); vis[x] = 1;
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(vis[to]) continue;
ans -= Calc(to, e[i].dis); Size = Max = size[to];
GetRoot(to, x); Solve(root);
}
} int main()
{
#ifndef ONLINE_JUDGE
file(cpp);
#endif Max = Size = n = read();
for(RG int i = 1, a, b, c; i < n; i++)
a = read(), b = read(), c = read(), add_edge(a, b, c), add_edge(b, a, c);
K = read(); GetRoot(1, 0); Solve(root); printf("%d\n", ans);
return 0;
}

最新文章

  1. JAligner的一个坑
  2. 对象-3.py
  3. mysql - 其它
  4. 【IOS笔记】About Events in iOS
  5. 搞懂offsetY、offsetTop、scrollTop、offsetHeight、scrollHeight
  6. 关于OpenCV做图像处理内存释放的一些问题
  7. nyoj 239 月老的难题【匈牙利算法+邻接表】
  8. 魅蓝Note2跑分 MT6753性能究竟如何
  9. IIS报500.0错误
  10. hdu1054 树状dp
  11. 【转】android加载大量图片内存溢出的三种解决办法
  12. GridView点击空白地方事件扩展
  13. javascript系列之this
  14. JavaScript之再谈回调与闭包
  15. C# 将字符串转为&amp;#2345;这种的 html实体编码
  16. 解决Ubuntu SMPlayer播放视频无声音问题
  17. 1523. K-inversions URAL 求k逆序对,,,,DP加树状数组
  18. forwardPort.go
  19. [转] KVM scalability and consolidation ratio: cache none vs cache writeback
  20. 在一些开源框架中,dist文件夹是什么意思

热门文章

  1. 洛谷 P4705 玩游戏
  2. python 中的pipe
  3. Guava包学习--Multiset
  4. seek()和tell()在文件里转移
  5. SpringBoot两种读取配置文件的方式
  6. 【腾讯敏捷转型No.6】如何打造称手的敏捷工具
  7. C++练习 | 在递增序列中查找最后一个小于等于指定数的元素
  8. MySql多表关联,根据某列取前N条记录问题
  9. svn配置教程
  10. vim8配置python3补全