tree 1s 128M  by hzw

czy神犇种了一棵树,他想知道地球的质量

给定一棵n个点的树,求树上经过点的个数≥K的路径数量ans

对于部分数据,树上某两点间会多出最多一条无向边

输入数据

n,m,K

接下来n行,每行u,v表示u与v间有无向边连接

输出数据

ans

样例数据

input

5 5 2

1 3

2 4

3 5

4 1

5 2

output

20

数据范围

30%的数据n,m<=5000

100%的数据n,m<=100000

其中有50%的数据满足m+1=n,具体如下

测试点

前3个小数据1树2链 3环+外向树

后7个大数据4-6树 7-8环 9-10环+外向树


如果没有环,那就是经典点分治题目啦。

题目保证有且只有一个环,那么我们先随便拆掉环上的一条边,然后用点分治算出不经过这条边的满足题意的路径数量。

ans需要加上经过这条边的满足题意的路径数量。

这个怎么求呢?

看我丑丑的图。。

环可以用并查集判断(注意每次更新fa[x]不然容易暴栈),要删的边就直接不要插入。

树状数组用来判断>=x的有多少个,注意0会死循环,加个偏移量,负数就直接升到1。

代码:

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7.  
  8. typedef long long LL;
  9. const int N=;
  10. int n,m,K,cx,cy,cl,tl,sl,len,has_circle;
  11. int first[N],c[N],s[N],t[N],d[N],mark[N],size[N],f[N],cir[N];
  12. struct node{
  13. int x,y,next;
  14. }a[*N];
  15. LL ans;
  16.  
  17. bool cmp(int x,int y){return x<y;}
  18.  
  19. void ins(int x,int y)
  20. {
  21. a[++len].x=x;a[len].y=y;
  22. a[len].next=first[x];first[x]=len;
  23. }
  24.  
  25. int findfa(int x)
  26. {
  27. if(f[x]==x) return x;
  28. return f[x]=findfa(f[x]);
  29. }
  30.  
  31. void add(int x,int val)
  32. {
  33. x++;
  34. for(int i=x;i>=;i-=(i&(-i))) c[i]+=val;
  35. }
  36. int getsum(int x)
  37. {
  38. x++;
  39. if(x<=) x=;
  40. int now=;
  41. for(int i=x;i<=n;i+=(i&(-i))) now+=c[i];
  42. return now;
  43. }
  44.  
  45. void find_root(int x,int fa,int tot,int &root)
  46. {
  47. size[x]=;
  48. bool bk=;
  49. for(int i=first[x];i;i=a[i].next)
  50. {
  51. int y=a[i].y;
  52. if(y==fa || mark[y]) continue;
  53. find_root(y,x,tot,root);
  54. size[x]+=size[y];
  55. if(*size[y]>tot) bk=;
  56. }
  57. if(bk && *(tot-size[x])<=tot) root=x;
  58. }
  59.  
  60. void DFS(int x,int fa,int tmp)
  61. {
  62. if(tmp)
  63. {
  64. d[x]=d[fa]+;
  65. ans+=getsum(K-d[x]);
  66. }
  67. t[++tl]=d[x];
  68. size[x]=;
  69. for(int i=first[x];i;i=a[i].next)
  70. {
  71. int y=a[i].y;
  72. if(y==fa || mark[y]) continue;
  73. DFS(y,x,tmp);
  74. size[x]+=size[y];
  75. }
  76. }
  77.  
  78. void dfs(int x,int tot)
  79. {
  80. find_root(x,,tot,x);
  81. sl=;s[++sl]=;add(,);
  82. mark[x]=;d[x]=;
  83. for(int i=first[x];i;i=a[i].next)
  84. {
  85. int y=a[i].y;
  86. if(mark[y]) continue;
  87. tl=;
  88. DFS(y,x,);
  89. for(int j=;j<=tl;j++)
  90. {
  91. s[++sl]=t[j];
  92. add(t[j],);
  93. }
  94. }
  95. for(int i=;i<=sl;i++) add(s[i],-);
  96. for(int i=first[x];i;i=a[i].next)
  97. {
  98. int y=a[i].y;
  99. if(mark[y]) continue;
  100. dfs(y,size[y]);
  101. }
  102. }
  103.  
  104. void find_circle(int x,int fa)
  105. {
  106. if(x==cy) {cir[++cl]=x;return ;}
  107. for(int i=first[x];i;i=a[i].next)
  108. {
  109. int y=a[i].y;
  110. if(y==fa) continue;
  111. find_circle(y,x);
  112. if(mark[y]) {cir[++cl]=x;mark[x]=;}
  113. }
  114. }
  115.  
  116. void solve_circle()
  117. {
  118. memset(c,,sizeof(c));
  119. memset(mark,,sizeof(mark));
  120. mark[cx]=mark[cy]=;
  121. find_circle(cx,);
  122.  
  123. // for(int i=1;i<=cl;i++) printf("%d ",cir[i]);printf("\n");
  124. memset(mark,,sizeof(mark));
  125. d[]=-;tl=;
  126. DFS(cy,,);
  127. for(int i=;i<=tl;i++) add(t[i],);
  128. for(int i=;i<=cl;i++) mark[cir[i]]=;
  129.  
  130. K--;
  131. for(int i=cl;i>=;i--)
  132. {
  133. tl=;
  134. mark[cir[i]]=;
  135. DFS(cir[i],,);
  136. for(int j=;j<=tl;j++) add(t[j],-);
  137. if(i<cl) d[cir[i]]=d[cir[i+]]+;
  138. DFS(cir[i],cir[i+],);
  139. mark[cir[i]]=;
  140. }
  141. }
  142.  
  143. int main()
  144. {
  145. // freopen("a.in","r",stdin);
  146. // freopen("a.out","w",stdout);
  147. freopen("tree.in","r",stdin);
  148. freopen("tree.out","w",stdout);
  149. scanf("%d%d%d",&n,&m,&K);K--;
  150. int x,y,xx,yy;
  151. ans=;len=;has_circle=;
  152. memset(c,,sizeof(c));
  153. memset(mark,,sizeof(mark));
  154. memset(first,,sizeof(first));
  155. for(int i=;i<=n;i++) f[i]=i;
  156. for(int i=;i<=m;i++)
  157. {
  158. scanf("%d%d",&x,&y);
  159. xx=findfa(x);yy=findfa(y);
  160. if(xx==yy)
  161. {
  162. has_circle=;
  163. cx=x;cy=y;
  164. }
  165. else
  166. {
  167. ins(x,y);ins(y,x);
  168. f[xx]=yy;
  169. }
  170. }
  171. // for(int i=1;i<=len;i+=2) printf("%d --> %d\n",a[i].x,a[i].y);
  172. dfs(,n);
  173. if(has_circle) solve_circle();
  174. printf("%lld\n",ans);
  175. return ;
  176. }

【bzoj3648】环套树+点分治+树状数组的更多相关文章

  1. CF 293 E Close Vertices (树的分治+树状数组)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题目:给出一棵树,问有多少条路径权值和不大于w,长 ...

  2. hdu_4918_Query on the subtree(树的分治+树状数组)

    题目链接:hdu_4918_Query on the subtree 题意: 给出一颗n个点的树,每个点有一个权值,有两种操作,一种是将某个点的权值修改为v,另一种是查询距离点u不超过d的点的权值和. ...

  3. [bzoj3155]Preprefix sum(树状数组)

    3155: Preprefix sum Time Limit: 1 Sec  Memory Limit: 512 MBSubmit: 1183  Solved: 546[Submit][Status] ...

  4. Codeforces 980E The Number Games - 贪心 - 树状数组

    题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗有$n$个点的树,$i$号点的权值是$2^{i}$要求删去$k$个点,使得剩下的点仍然连通,并且总权值和最大,问删去的所有点的编号. ...

  5. 【BZOJ-3648】寝室管理 环套树 + 树状数组 + 点分治

    3648: 寝室管理 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 239  Solved: 106[Submit][Status][Discuss] ...

  6. bzoj3648: 寝室管理(环套树+点分治)

    好题..写了两个半小时hh,省选的时候要一个半小时内调出这种题目还真是难= = 题目大意是给一棵树或环套树,求点距大于等于K的点对数 这里的树状数组做了一点变换.不是向上更新和向下求和,而是反过来,所 ...

  7. BZOJ 3648: 寝室管理( 点分治 + 树状数组 )

    1棵树的话, 点分治+你喜欢的数据结构(树状数组/线段树/平衡树)就可以秒掉, O(N log^2 N). 假如是环套树, 先去掉环上1条边, 然后O(N log^2 N)处理树(同上); 然后再O( ...

  8. hdu 4742 Pinball Game 3D 分治+树状数组

    离散化x然后用树状数组解决,排序y然后分治解决,z在分治的时候排序解决. 具体:先对y排序,solve(l,r)分成solve(l,mid),solve(mid+1,r), 然后因为是按照y排序,所以 ...

  9. BZOJ1176---[Balkan2007]Mokia (CDQ分治 + 树状数组)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1176 CDQ第一题,warush了好久.. CDQ分治推荐论文: 1 <从<C ...

随机推荐

  1. Notes of the scrum meeting before publishing(12.17)

    meeting time:18:30~20:30p.m.,December 17th,2013 meeting place:3号公寓一层 attendees: 顾育豪                  ...

  2. Alpha冲刺——第四天

    Alpha第四天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...

  3. 【week6】用户数

    小组名称:nice! 小组成员:李权 于淼 杨柳 刘芳芳 项目内容:约跑app alpha发布48小时以后用户数如何,是否达到预期目标,为什么,是否需要改进,如何改进(或理性估算). 首先我们的app ...

  4. PAT-2018年冬季考试-乙级

    1091 N-自守数 代码: #include <bits/stdc++.h> using namespace std; int T; int A(int a) { ; while(a) ...

  5. 关于&$地址传递的练习

    php默认为传值传递: 既: $a=10;$b=$a; //$b为10$a=+10; //$a 为20 echo $a.'和'.$b;  # $a is 20 and $b is 10! 要是想变为地 ...

  6. 初入py

    1.下载工具sublime 我的网盘下载地址:https://pan.baidu.com/s/18-U1ZSg_zHoSAqUuvXj_PQ 直接解压即可 2.配置py27 在新建的文件里面编辑并保存 ...

  7. E2202 Required package 'rtl' not found"

    最近重新下载了一个delphi Berlin 10.1.2绿色版本,解压后剪切到别的盘上了,一些需要直接编译的.dpk包,例如fastReport都不能了,都提示E2202 Required pack ...

  8. 前端基础:HTML标签(下)

    前端基础HTML标签(下) 1.表单 表单的功能主要用于向服务器传输数据,从而实现客户端与Web服务器的交互.表单能够包含input系列标签,比如:文本字段.复选框.单选按钮.提交按钮等:表单还包含t ...

  9. Android 内核--Binder架构分析

    一.Binder架构 在Android中,Binder用于完成进程间通信(IPC),即把多个进程关联在一起.比如,普通应用程序可以调用音乐播放服务提供的播放.暂停.停止等功能.Binder工作在Lin ...

  10. POJ1743:Musical Theme——题解

    http://poj.org/problem?id=1743 给一段数,求最大相似子串长度,如果没有输出0. 相似子串定义: 1.两个不重叠的子串,其中一个是另一个加/减一个数得来的. 2.长度> ...