【题解】P4178 Tree

一道点分治模板好题

不知道是不是我见到的题目太少了,为什么这种题目都是暴力开值域的桶QAQ??

问点对,考虑点分治吧。直接用值域树状数组开下来,统计的时候直接往树状数组里面查询。记得每一层先把这一层的答案统计一下,统计的方法就是刚刚讲的在桶里查。

问题是回溯,值域不大,所以常数还可以,但是我们最好还是开个\(temp\)把我们做修改的地方记录一下,在\(calc\)返回的时候直接回溯。

时间复杂度\(nlog^2n\) 有一些细节需要注意。比如要把\(d[]\)的先统计进去。这一部分答案是从节点到根,没有被点分治覆盖到。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define RP(t,a,b) for(register int t=(a),edd=(b);t<=edd;++t)
  4. #define DRP(t,a,b) for(register int t=(a),edd=(b);t>=edd;--t)
  5. #define ERP(t,a) for(register int t=head[a];t;t=e[t].nx)
  6. #define Max(a,b) ((a)<(b)?(b):(a))
  7. #define Min(a,b) ((a)<(b)?(a):(b))
  8. #define midd register int mid=(l+r)>>1
  9. #define TMP template < class ccf >
  10. #define lowbit(x) ((x)&(-x))
  11. TMP inline ccf qr(ccf b){
  12. char c=getchar();
  13. int q=1;
  14. ccf x=0;
  15. while(c<48||c>57)
  16. q=c==45?-1:q,c=getchar();
  17. while(c>=48&&c<=57)
  18. x=x*10+c-48,c=getchar();
  19. return q==-1?-x:x;
  20. }
  21. const int maxn=40000+15;
  22. int n,m;
  23. struct E{
  24. int to,w,nx;
  25. }e[maxn<<1];
  26. int head[maxn];
  27. int cnt;
  28. inline void add(int fr,int to,int w,bool f){
  29. e[++cnt]=(E){to,w,head[fr]};
  30. head[fr]=cnt;
  31. if(f)
  32. add(to,fr,w,0);
  33. }
  34. bool usd[maxn];
  35. int siz[maxn];
  36. int spa[maxn];
  37. int sav[maxn];
  38. int d[maxn];
  39. int rt;
  40. int k;
  41. int data[20005];
  42. int q[maxn];
  43. int sum;
  44. int ans;
  45. inline void add(int x,int qaq){
  46. for(register int t=x+1;t<=20001;t+=lowbit(t))data[t]+=qaq;
  47. }
  48. inline int ask(int x){register int ret=0;
  49. for(register int t=Min(x+1,20001);t>0;t-=lowbit(t))ret+=data[t];
  50. return ret;
  51. }
  52. void dfsroot(int now,int last){
  53. siz[now]=1;
  54. spa[now]=0;
  55. ERP(t,now){
  56. if(e[t].to!=last&&!usd[e[t].to]){
  57. dfsroot(e[t].to,now);
  58. siz[now]+=siz[e[t].to];
  59. spa[now]=Max(spa[now],siz[e[t].to]);
  60. }
  61. }
  62. spa[now]=Max(spa[now],sum-siz[now]);
  63. if(spa[now]<spa[rt]||rt==0)
  64. rt=now;
  65. }
  66. void dfsdis(int now,int last,int ew){
  67. d[now]=d[last]+ew;
  68. sav[++sav[0]]=d[now];
  69. ERP(t,now){
  70. if(e[t].to!=last&&!usd[e[t].to]){
  71. dfsdis(e[t].to,now,e[t].w);
  72. }
  73. }
  74. }
  75. inline void calc(int now){
  76. register int p=0;
  77. ERP(t,now){
  78. if(!usd[e[t].to]){
  79. sav[0]=0;
  80. dfsdis(e[t].to,0,e[t].w);
  81. RP(i,1,sav[0])
  82. ans+=ask(k-sav[i]);
  83. RP(i,1,sav[0])
  84. if(sav[i]<=k) ans++;
  85. RP(i,1,sav[0]) add(sav[i],1);
  86. RP(i,1,sav[0]) q[++p]=sav[i];
  87. }
  88. }
  89. RP(t,1,p)
  90. add(q[t],-1);
  91. }
  92. void solve(int now){
  93. usd[now]=1;
  94. calc(now);
  95. ERP(t,now){
  96. if(!usd[e[t].to]){
  97. sum=siz[e[t].to];
  98. rt=0;
  99. dfsroot(e[t].to,0);
  100. solve(rt);
  101. }
  102. }
  103. }
  104. int main(){
  105. #ifndef ONLINE_JUDGE
  106. freopen("in.in","r",stdin);
  107. freopen("out.out","w",stdout);
  108. #endif
  109. n=qr(1);
  110. for(register int t=1,t1,t2,t3;t<n;++t){
  111. t1=qr(1);
  112. t2=qr(1);
  113. t3=qr(1);
  114. add(t1,t2,t3,1);
  115. }
  116. k=qr(1);
  117. sum=n;
  118. dfsroot(1,0);
  119. solve(rt);
  120. cout<<ans<<endl;
  121. return 0;
  122. }

【题解】[P4178 Tree]的更多相关文章

  1. luogu P4178 Tree

    题目链接 luogu P4178 Tree 题解 点分治 代码 // luogu-judger-enable-o2 #include<cstdio> #include<algorit ...

  2. POJ1471 Tree/洛谷P4178 Tree

    Tree P4178 Tree 点分治板子. 点分治就是直接找树的重心进行暴力计算,每次树的深度不会超过子树深度的\(\frac{1}{2}\),计算完就消除影响,找下一个重心. 所以伪代码: voi ...

  3. [Luogu P4178]Tree 题解(点分治+平衡树)

    题目大意 给定一棵树,边带权,问有多少点对满足二者间距离$\leq K$,$n \leq 40000$. 题解 点分治专题首杀!$Jackpot!$ (本来看着题意比较简单想捡个软柿子捏,结果手断了… ...

  4. [LeetCode 题解]: Binary Tree Preorder Traversal

    前言   [LeetCode 题解]系列传送门:  http://www.cnblogs.com/double-win/category/573499.html   1.题目描述 Given a bi ...

  5. [LeetCode 题解]: Symmetric Tree

    前言   [LeetCode 题解]系列传送门:  http://www.cnblogs.com/double-win/category/573499.html   1.题目描述   Given a ...

  6. 洛谷P4178 Tree (点分治)

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

  7. 竞赛题解 - Broken Tree(CF-758E)

    Broken Tree(CF-758E) - 竞赛题解 贪心复习~(好像暴露了什么算法--) 标签:贪心 / DFS / Codeforces 『题意』 给出一棵以1为根的树,每条边有两个值:p-强度 ...

  8. [题解] 树(tree)

    题目大意 ​ 给定一颗 \(N\) 个点的有根树,其中 \(1\) 是树根,除了 \(1\) 以外的其他点 \(u\) 有唯一的父亲 \(Father_u\).同时,给定 \(M\) 条路径,第 \( ...

  9. leetcode题解:Tree Level Order Traversal II (二叉树的层序遍历 2)

    题目: Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from ...

随机推荐

  1. vs2013 x64 编译汇编代码

    x64不再支持__asm, 只能单独放在一个.asm中. xxx.asm--------属性 应用    会出现 自定义生成工具.  下面黑体是我们修改的内容.

  2. 多线程一共就俩问题:1.线程安全(访问共享数据) 2.线程通信(wait(),notify())

    多线程一共就俩问题:1.线程安全(访问共享数据) 2.线程通信(wait(),notify()) 1.线程安全,无非就是加锁,访问共享资源时,synchronized 2.线程通信,就是控制各个线程之 ...

  3. iOS使用MD5 - 字符串加密至MD5&获取文件MD5

    iOS 字符串加密至MD5 + (NSString *) md5:(NSString *)str { unsigned ]; CC_MD5( cStr, strlen(cStr), result ); ...

  4. 对数据进行GZIP压缩和解压

    public class GzipUtils { /** * 对字符串进行gzip压缩 * @param data * @return * @throws IOException */ public ...

  5. Web终端之使用shellinabox在浏览器进行ssh登录

    shellinbox有一个内建的web server作为基本的web ssh client,允许你通过指定的端口访问linux服务器的ssh shell,只要你的浏览器支持AJAX/JS/CSS就可以 ...

  6. 对国外某hotel的内网域简单渗透

    Penetration Testing不单单是一个博客,更热衷于技术分享的平台. 本文将讲述对国外某一hotel的渗透测试,让更多的人安全意识得到提高,有攻才有防,防得在好,也有疏忽的地方,这就是为啥 ...

  7. Mongo JavaTest

    import com.mongodb.MongoClient; import com.mongodb.DB; import com.mongodb.DBCollection; import com.m ...

  8. Java使用笔记之对象比较

    1.关于java对象的比较,经常会遇见比较某个两个对象的多个属性是否相等,可以通过重写对象equals方法来实现. 比如有两个User,如果姓名和年龄相等的话,我们就可以认为他们重复的数据.那么我们就 ...

  9. SQL Server -使用表触发器记录表插入,更新,删除行数

    1.如何使用sql获取当前session用户名和机器名 Select CURRENT_USER,Host_name() 2.如何在表触发器中获取当前表名称 SELECT OBJECT_SCHEMA_N ...

  10. 结构体定义:struct与typedef struct

    https://blog.csdn.net/haiou0/article/details/6877718?tdsourcetag=s_pcqq_aiomsg https://blog.csdn.net ...