好题。。写了两个半小时hh,省选的时候要一个半小时内调出这种题目还真是难= =

题目大意是给一棵树或环套树,求点距大于等于K的点对数

这里的树状数组做了一点变换。不是向上更新和向下求和,而是反过来,所以求和的时候sum(k)实际上是求k到n的和

所以我们要求大于等于k的dis的次数和,就是求sum(1,k-1),注意k要减一

如果是树,就是常规的点分治,然后用树状数组维护dis【t】出现的次数

如果是环套树,找环之后割掉一条边,然后先求这棵树的答案。接着考虑过了这条割掉的边s--t的情况:我们以这条边的一点t为起点,对于环上的每个点(即每棵子树的根),我们求出这棵子树的所有dis后,dis+cir_len-i为所求链的第一部分,链的第二部分的长度为k-(dis+cir_len-i),用树状数组求就可以了。更新树状数组的时候不是更新dis,而是dis+i;i即根到割的那条边的另一个点s的距离&&这条割边

完美解决。。然而常数还是很大,跑了两秒多

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. #define INF 0x3f3f3f3f
  5. #define LL long long
  6. using namespace std;
  7. ;
  8. struct node{
  9. int to,next;
  10. }e[maxn*];
  11. int n,m,K,head[maxn],size[maxn],vis[maxn],sz,total,root,dis[maxn],tot,fa[maxn];
  12. ;
  13. LL p[maxn*],ans;
  14.  
  15. void insert(int u, int v){
  16. e[++tot].to=v; e[tot].next=head[u]; head[u]=tot;
  17. }
  18.  
  19. void add(int x, LL c){
  20. for (;x;x-=x&-x) p[x]+=c;
  21. }
  22. LL query(int x){ //注意:这里的树状数组是倒过来的, query(1,k) 是求得k+1到n
  23. LL ret=;
  24. ) x=;
  25. *n;x+=x&-x) ret+=p[x];
  26. return ret;
  27. }
  28.  
  29. void getroot(int u, int f){
  30. size[u]=; ;
  31. for (int v,i=head[u]; i; i=e[i].next){
  32. if (vis[v=e[i].to] || v==f || i==ban1 || i==ban2) continue;
  33. getroot(v,u);
  34. size[u]+=size[v];
  35. mx=max(mx,size[v]);
  36. }
  37. mx=max(mx,total-size[u]);
  38. if (mx<sz) sz=mx,root=u;
  39. }
  40.  
  41. void getdis(int u, int f, int d){
  42. dis[++tot]=d;
  43. for (int i=head[u],v; i; i=e[i].next){
  44. if (vis[v=e[i].to] || v==f || i==ban1 || i==ban2) continue;
  45. getdis(v,u,d+);
  46. }
  47. }
  48.  
  49. void work(int u){
  50. total=size[u]?size[u]:n;
  51. sz=INF;
  52. getroot(u,); u=root;
  53. vis[u]=; tot=;
  54. ; i; i=e[i].next){
  55. if (vis[v=e[i].to] || i==ban1 || i==ban2) continue;
  56. last=tot;
  57. getdis(v,,); //printf("%d\n", tot);
  58. ; j<=tot; j++) ans+=query(K--dis[j]);
  59. ; j<=tot; j++) add(dis[j],);
  60. }
  61. ans+=query(K-);
  62. );
  63. for (int v,i=head[u]; i; i=e[i].next)
  64. if (!vis[v=e[i].to] && i!=ban1 && i!=ban2) work(v);
  65. }
  66.  
  67. void find_cir(int u, int f){
  68. vis[u]=; if (len) return;//printf(" %d\n", u);
  69. for (int i=head[u],v; i; i=e[i].next){
  70. v=e[i].to;
  71. if (v==f || len) continue;
  72. fa[v]=u;// printf("now %d\n", u);
  73. if (vis[v]){
  74. ban1=i; ban2=i^;
  75. for (int x=fa[v]; x!=v; x=fa[x]) cir[++len]=x; cir[++len]=v;
  76. return;
  77. }
  78. find_cir(v,u);
  79. }
  80. }
  81.  
  82. void cut(){
  83. ; i<=n; i++) vis[i]=;
  84. work();// printf(" %lld\n", ans);
  85. ; i<=n; i++) p[i]=0LL,vis[i]=;
  86. ; i<=len; i++) vis[cir[i]]=;
  87. ; i<=len; i++){
  88. ;
  89. getdis(u,,); //printf(" %d\n", tot);
  90. ; j<=tot; j++) ans+=query(K-dis[j]-(len-i+));//, printf("%lld\n", ans);
  91. );
  92. }
  93. }
  94.  
  95. int main(){
  96. scanf(;
  97. ,u,v; i<=m; i++){
  98. scanf("%d%d", &u, &v);
  99. insert(u,v); insert(v,u);
  100. }
  101. ) work();
  102. else{
  103. find_cir(,);
  104. cut();
  105. }
  106. printf("%lld\n", ans);
  107. ;
  108. }

bzoj3648: 寝室管理(环套树+点分治)的更多相关文章

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

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

  2. BZOJ3648 寝室管理 【点分治 + 环套树】

    3648: 寝室管理 Time Limit: 40 Sec  Memory Limit: 512 MB Submit: 366  Solved: 152 [Submit][Status][Discus ...

  3. BZOJ3648 : 寝室管理

    求环套外向树上节点数不小于K的路径数. 首先树的话直接点分治+树状数组$O(n\log^2n)$搞定 环套树的话,先删掉多余的边(a,b) 然后变成了一棵树,直接点分治 然后在树上找到a到b的路径,将 ...

  4. 【bzoj3648】环套树+点分治+树状数组

    tree 1s 128M  by hzw czy神犇种了一棵树,他想知道地球的质量 给定一棵n个点的树,求树上经过点的个数≥K的路径数量ans 对于部分数据,树上某两点间会多出最多一条无向边 输入数据 ...

  5. 【BZOJ3648】寝室管理 树分治

    [BZOJ3648]寝室管理 Description T64有一个好朋友,叫T128.T128是寄宿生,并且最近被老师叫过去当宿管了.宿管可不是一件很好做的工作,碰巧T128有一个工作上的问题想请T6 ...

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

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

  7. [ARC083F] Collecting Balls [建二分图+环套树定向+建拓扑图+树的拓扑序计数]

    题面 [传送门](https://arc083.contest.atcoder.jp/tasks/arc083_d) 思路 这是一道真正的好题 第一步:转化模型 行列支配类的问题,常见做法就是把行和列 ...

  8. 【BZOJ-1040】骑士 树形DP + 环套树 + DFS

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3312  Solved: 1269[Submit][Status ...

  9. 【BZOJ】1040: [ZJOI2008]骑士(环套树dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1040 简直不能再神的题orz. 蒟蒻即使蒟蒻,完全不会. 一开始看到数据n<=1000000就 ...

随机推荐

  1. oracle打补丁

    oracle 数据库补丁安装(单实例) ------------24006111 注:务必先安装24006111再安装24315821,否则无法进行正常的补丁安装流程.1.关闭数据库监听和数据库实例 ...

  2. [转]VS2012 快捷键

    Ctrl+E,D ----格式化全部代码       Ctrl+A+K+F Ctrl+E,F ----格式化选中的代码     Ctrl+K+F CTRL + SHIFT + B生成解决方案   Al ...

  3. xcode8.2 打包问题

    如图 在 iOS 到处 ipa包的时候 会有四个选项   PS:证书的账号密码 是需要填写的1.Save for iOS App Store Deployment(部署) sign and packa ...

  4. 如何托管ASP.NET Core应用到Windows Service中

    (此文章同时发表在本人微信公众号"dotNET开发经验谈",欢迎右边二维码来关注.) 题记:正在构思一个中间件的设计,考虑是否既可以使用最新的技术,也可以兼顾传统的部署模式.所以有 ...

  5. Android学习资源整理

    官方文档:https://developer.android.com/guide/index.html (万万没想到居然有中文) 网友整理的学习笔记,挺不错的 http://www.runoob.co ...

  6. linux简单命令

    查看服务器开启的进程信息[root@CentOSHT ~]# top 其中第一行的  Load average 参数是服务器负载的意思,

  7. Ubuntu——apt && dpkg参考

    一.apt apt-cache search # ------(package 搜索包) apt-cache show #------(package 获取包的相关信息,如说明.大小.版本等) sud ...

  8. Java 之 数据库

    1.SQL--结构化查询语言 a.分类:①DDL--数据定义语言 ②DQL--数据查询语言 ③DML--数据操作语言 ④DCL--数据控制语言 b.DDL:包括对数据库的创建.使用.删除,对表的创建. ...

  9. STC系列STC10F芯片解密STC10L单片机破解复制技术

    STC系列STC10F芯片解密STC10L单片机破解 STC10F12XE | STC10F12 | STC10F10XE | STC10F10解密 STC10F08XE | STC10F08 | S ...

  10. .NET string字符串的截取、移除、替换、插入

    在实际开发中经常要用到string的各种截取等操作,在这里总结自己认为经常出现的.NET 字符串的截取.移除.替换.插入操作,方面以后查阅. 前台代码: <%@ Page Language=&q ...