BZOJ1468

POJ1741

题意: 计算树上距离<=K的点对数

我们知道树上一条路径要么经过根节点,要么在同一棵子树中。

于是对一个点x我们可以这样统计: 计算出所有点到它的距离dep[],排序后可以O(n)求得<=K的点对数量。

但画个图后我们可以发现,对于在同一棵子树中的路径被重复计算过了。于是我们Ans-=Calc(v),减去一棵子树中的路径答案,但是这并不是之前x到它们的路径,于是给v的dep[]设一个初始值为w(x->v路径权值)。

这样x的答案就计算完了,将这一过程记作Solve(x)。

考虑如何计算所有点。DFS的效率是和树深有关的。计算x->v时,我们选取v子树上的重心作为下次Solve()的参数。

选取重心每次都会使树的节点个数减半,因此递归深度最坏(链)是logn的。

这样便可O(nlog^2n)解决该题。

  1. //2524kb 656ms
  2. #include <cstdio>
  3. #include <cctype>
  4. #include <algorithm>
  5. //#define gc() getchar()
  6. #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
  7. const int N=40005,MAXIN=1e5;
  8. int n,K,root,Min,Ans,Enum,H[N],nxt[N<<1],to[N<<1],val[N<<1],dep[N],sz[N],D[N];
  9. bool vis[N];
  10. char IN[MAXIN],*SS=IN,*TT=IN;
  11. inline int read()
  12. {
  13. int now=0;register char c=gc();
  14. for(;!isdigit(c);c=gc());
  15. for(;isdigit(c);now=now*10+c-'0',c=gc());
  16. return now;
  17. }
  18. inline void AddEdge(int u,int v,int w)
  19. {
  20. to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, val[Enum]=w;
  21. to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, val[Enum]=w;
  22. }
  23. void Get_Root(int x,int f,int tot)
  24. {
  25. int mx=0; sz[x]=1;
  26. for(int v,i=H[x]; i; i=nxt[i])
  27. if(!vis[to[i]] && to[i]!=f)
  28. {
  29. Get_Root(v=to[i],x,tot), sz[x]+=sz[v];
  30. if(sz[v]>mx) mx=sz[v];
  31. }
  32. mx=std::max(mx,tot-sz[x]);
  33. if(mx<Min) Min=mx, root=x;
  34. }
  35. void DFS(int x,int f)
  36. {
  37. D[++D[0]]=dep[x];
  38. for(int i=H[x]; i; i=nxt[i])
  39. if(!vis[to[i]]&&to[i]!=f)
  40. dep[to[i]]=dep[x]+val[i], DFS(to[i],x);
  41. }
  42. int Calc(int x,int v)
  43. {
  44. D[0]=0, dep[x]=v, DFS(x,-1);
  45. std::sort(D+1,D+1+D[0]);
  46. int l=1,r=D[0],res=0;
  47. while(l<r)
  48. if(D[l]+D[r]<=K) res+=r-l,++l;
  49. else --r;
  50. return res;
  51. }
  52. void Solve(int x)
  53. {
  54. Ans+=Calc(x,0), vis[x]=1;
  55. for(int v,i=H[x]; i; i=nxt[i])
  56. if(!vis[to[i]])
  57. {
  58. Ans-=Calc(v=to[i],val[i]);
  59. Min=N, Get_Root(v,x,sz[v]), Solve(root);
  60. }
  61. }
  62. int main()
  63. {
  64. n=read();
  65. for(int u,v,w,i=1; i<n; ++i) u=read(),v=read(),w=read(),AddEdge(u,v,w);
  66. K=read();
  67. Min=N, Get_Root(1,-1,n), Solve(root);
  68. printf("%d",Ans);
  69. return 0;
  70. }

BZOJ.1468.Tree(点分治)的更多相关文章

  1. bzoj 1468 Tree(点分治模板)

    1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1527  Solved: 818[Submit][Status][Discuss] ...

  2. BZOJ 1468 Tree 【模板】树上点分治

    #include<cstdio> #include<algorithm> #define N 50010 #define M 500010 #define rg registe ...

  3. BZOJ 1468: Tree

    Description 真·树,问距离不大于 \(k\) 的点对个数. Sol 点分治. 同上. Code /********************************************* ...

  4. 【刷题】BZOJ 1468 Tree

    Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是 ...

  5. bzoj 1468 Tree 点分

    Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1972  Solved: 1101[Submit][Status][Discuss] Desc ...

  6. 【BZOJ-1468】Tree 树分治

    1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1025  Solved: 534[Submit][Status][Discuss] ...

  7. bzoj 2212 Tree Rotations

    bzoj 2212 Tree Rotations 考虑一个子树 \(x\) 的左右儿子分别为 \(ls,rs\) .那么子树 \(x\) 内的逆序对数就是 \(ls\) 内的逆序对数,\(rs\) 内 ...

  8. [BZOJ 3456]城市规划(cdq分治+FFT)

    [BZOJ 3456]城市规划(cdq分治+FFT) 题面 求有标号n个点无向连通图数目. 分析 设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量 ...

  9. [BZOJ 2989]数列(CDQ 分治+曼哈顿距离与切比雪夫距离的转化)

    [BZOJ 2989]数列(CDQ 分治) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]| ...

随机推荐

  1. Linux 获取设备树源文件(DTS)里描述的资源【转】

    转自:http://www.linuxidc.com/Linux/2013-07/86839.htm 转自:http://blog.sina.com.cn/s/blog_636a55070101mce ...

  2. ES系列十、ES常用查询API

    1.term查询 { "query": { "term": { "title": "crime" } } } 1.1.指 ...

  3. 自定义el标签

    编写java代码 package com.ycjk.common; public class FormatJSEltarg { public static String format(String s ...

  4. 转载:abstract的方法是否可同时是static,是否可同时是native,是否可同时是synchronized?

    原文:http://blog.csdn.net/fhm727/article/details/5222965 1.abstract与static (what) abstract:用来声明抽象方法,抽象 ...

  5. rt3070无线网卡移植到开发板

    Rt3070无线网卡AP功能移植到GEC210一.平台开发板:GEC210 无线网卡:RT3070主机:VMWare--Ubuntu 10.04 LTS内核版本:linux-2.6.35.7编译器:a ...

  6. mysql语句判断是否存在记录,没有则插入新纪录否则不执行

    1 前言 由于项目需要,当某个表如果有记录,就不执行加入语句,否则加入新纪录(测试数据).思路是:判断表的记录是否为空,然后再决定是否插入 2 代码 DROP PROCEDURE IF EXISTS ...

  7. Android 动画:你真的会使用插值器与估值器吗?

    目录   目录 1. 插值器(Interpolator) 1.1 简介 定义:一个接口 作用:设置 属性值 从初始值过渡到结束值 的变化规律 如匀速.加速 & 减速 等等 即确定了 动画效果变 ...

  8. python下图像读取方式以及效率对比

    https://zhuanlan.zhihu.com/p/30383580 opencv速度最快,值得注意的是mxnet的采用多线程读取的方式,可大大加速

  9. 从html页面中抽取table表格数据

    /** * [getDataFromTrElems 获取表格行元素数据] * @param {[Object]} trElems [trs dom] * @param {[String]} type ...

  10. 采用busybox 代替android 自带的shell

    折腾了几天,被Android那点儿少得可怜的shell命令折磨的死去活来,终于下定了革命的决心.看一下怎么把渺小的toolbox替换成伟大的busybox吧.先大致描述一下Android系统中的she ...