点分治 模板

╰半橙微兮° 2023-08-17 17:36 243阅读 0赞

debug了一晚上bug,竟然是爆了int 。再次感叹自己的码力

点分治模板,求距离在 n-L-1,n-R-2 区间内的点对数,

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int M=1e5+50;
  4. #define ll long long
  5. struct Node{int to,nex;}e[M<<1];
  6. int n,L,R,mx,sum,rt,cnt,siz[M],head[M<<1],v[M],p[M];
  7. ll res;
  8. void add(int x,int y){
  9. e[cnt].to=y;e[cnt].nex=head[x];head[x]=cnt++;
  10. e[cnt].to=x;e[cnt].nex=head[y];head[y]=cnt++;
  11. }
  12. void getrt(int x,int f){
  13. siz[x]=1;int mm=0;
  14. for(int to,i=head[x];~i;i=e[i].nex){
  15. to=e[i].to;
  16. if(to==f||v[to])continue;
  17. getrt(to,x);
  18. siz[x]+=siz[to];
  19. if(mm<siz[to])mm=siz[to];
  20. }
  21. if(mm<sum-siz[x])mm=sum-siz[x];
  22. if(mx>mm)mx=mm,rt=x;
  23. }
  24. void getdis(int x,int f,int dis,int k){
  25. if(dis>k)return ;
  26. p[++p[0]]=dis;
  27. for(int to,i=head[x];~i;i=e[i].nex){
  28. to=e[i].to;
  29. if(to==f||v[to])continue;
  30. getdis(to,x,dis+1,k);
  31. }
  32. }
  33. ll cal(int x,int dis,int k){
  34. ll ans=0;p[0]=0;
  35. getdis(x,-1,dis,k);
  36. sort(p+1,p+p[0]+1);
  37. for(int i=1,j=p[0];i<j;i++){
  38. while(p[i]+p[j]>k&&i<j)j--;
  39. ans+=j-i;
  40. }
  41. return ans;
  42. }
  43. void work(int x,int k){
  44. res+=cal(x,0,k);
  45. v[x]=1;
  46. for(int to,i=head[x];~i;i=e[i].nex){
  47. to=e[i].to;
  48. if(v[to])continue;
  49. res-=cal(to,1,k);
  50. mx=0x3f3f3f3f;
  51. sum=siz[to];//t点
  52. getrt(to,-1);
  53. work(rt,k);
  54. }
  55. }
  56. ll slove(int k){
  57. if(k<=0)return 0;
  58. res=0;
  59. memset(v,0,sizeof(v));
  60. mx=0x3f3f3f3f;sum=n;
  61. getrt(1,-1);work(rt,k);
  62. return res;
  63. }
  64. int main(){
  65. // freopen("awesome.in","r",stdin);
  66. int T;cin>>T;
  67. while(T--){
  68. memset(head,-1,sizeof(head));cnt=1;
  69. cin>>n>>L>>R;
  70. for(int x,y,i=1;i<n;i++)cin>>x>>y,add(x,y);
  71. cout<<slove(n-L-1)-slove(n-R-2)<<endl;
  72. }
  73. return 0;
  74. }

发表评论

表情:
评论列表 (有 0 条评论,243人围观)

还没有评论,来说两句吧...

相关阅读

    相关 分治-模板

    可能一步步克服恐惧的过程就是成功,所以只管面对恐惧,不思考结果, 24分钟敲模板,这是点分治第一次敲的这么顺利,纪念一下。 洛谷:2634.求距离是三的倍数的点对数

    相关 分治初步

      点分治是一种常用于处理树上点对关系的分治算法。   一、算法介绍   提到点分治,我们先来看一道例题:[洛谷P3806 【模板】点分治1][P3806 _1]

    相关 分治学习笔记

    哗我看了一下好像没有很详细专门讲分治的blog?那就主要先学一下点分治吧,其他的……等我记得把C++一本通带到机房来再说吧先咕着啦 > 写在前面 > > 刷题进度 > >

    相关 分治

      [传送门][Link 1](洛谷) UPDATE:关于代码中时间复杂度的更正——在代码中每一次都要通过遍历一遍询问来得到答案,所以时间复杂度是O(NMlogN), !

    相关 [笔记]分治

    基本思路:点分治,是一种针对可带权树上简单路径统计问题的算法。对于一个节点,只解决经过这棵子树的根节点的路径,对于子节点问题下推子树。 //当初的主要问题是vis[]