传送门

nmyzd,mgdhls,bnmbzdgdnlql,a,wgttxfs

对于一个点\(a\),点\(b\)只有可能是他的祖先或者在\(a\)子树里

如果点\(b\)是\(a\)祖先,那么答案为a子树大小\(sz_a-1\)

否则,答案为\(sz_b-1\)

加上\(k\)的限制后,如果根节点1的深度\(de_1=1\)那么节点\(a\)的答案就是\(\sum_{b在a子树中,b\ne a,dist(a,b)\leq k}\ \ (sz_b-1)+\min(k,de_a-1)*(sz_a-1)\).后半段可以直接算,前半段的话,对每个节点开个线段树,保存子树中深度为某个值的\(\sum sz_a-1\),在遍历的时候合并线段树,查询的时候就查询区间\([de_a+1,de_a+k]\)

  1. // luogu-judger-enable-o2
  2. #include<bits/stdc++.h>
  3. #define LL long long
  4. #define il inline
  5. #define re register
  6. #define db double
  7. #define eps (1e-7)
  8. using namespace std;
  9. const int N=300000+10;
  10. const LL inf=(1ll<<50);
  11. il LL rd()
  12. {
  13. re LL x=0,w=1;re char ch=0;
  14. while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
  15. while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
  16. return x*w;
  17. }
  18. int to[N<<1],nt[N<<1],hd[N],tot=1;
  19. il void add(int x,int y)
  20. {
  21. ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
  22. ++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
  23. }
  24. LL s[N*30];
  25. int ch[N*30][2],tt;
  26. #define mid ((l+r)>>1)
  27. il void psup(int o){s[o]=s[ch[o][0]]+s[ch[o][1]];}
  28. void bui(int o,int l,int r,int lx,LL x)
  29. {
  30. if(l==r){s[o]=x;return;}
  31. if(lx<=mid) bui(ch[o][0]=++tt,l,mid,lx,x);
  32. else bui(ch[o][1]=++tt,mid+1,r,lx,x);
  33. psup(o);
  34. }
  35. int merge(int o1,int o2)
  36. {
  37. if(!o1) return o2;
  38. if(!o2||o1==o2) return o1;
  39. int o3=++tt;
  40. s[o3]=s[o1]+s[o2];
  41. ch[o3][0]=merge(ch[o1][0],ch[o2][0]);
  42. ch[o3][1]=merge(ch[o1][1],ch[o2][1]);
  43. return o3;
  44. }
  45. LL quer(int o,int l,int r,int ll,int rr)
  46. {
  47. if(!o) return 0;
  48. if(ll<=l&&r<=rr) return s[o];
  49. LL an=0;
  50. if(ll<=mid) an+=quer(ch[o][0],l,mid,ll,rr);
  51. if(rr>mid) an+=quer(ch[o][1],mid+1,r,ll,rr);
  52. return an;
  53. }
  54. int n,m,rt[N];
  55. int sz[N],de[N];
  56. void dfs(int x,int ffa)
  57. {
  58. sz[x]=1;
  59. for(int i=hd[x];i;i=nt[i])
  60. {
  61. int y=to[i];
  62. if(y==ffa) continue;
  63. de[y]=de[x]+1;
  64. dfs(y,x);
  65. sz[x]+=sz[y];
  66. }
  67. if(sz[x]>1)
  68. {
  69. bui(rt[x]=++tt,1,n,de[x],sz[x]-1);
  70. for(int i=hd[x];i;i=nt[i])
  71. {
  72. int y=to[i];
  73. if(y==ffa) continue;
  74. rt[x]=merge(rt[x],rt[y]);
  75. }
  76. }
  77. }
  78. int main()
  79. {
  80. n=rd(),m=rd();
  81. for(int i=1;i<n;i++) add(rd(),rd());
  82. de[1]=1;
  83. dfs(1,0);
  84. while(m--)
  85. {
  86. int p=rd(),k=rd();
  87. printf("%lld\n",quer(rt[p],1,n,de[p]+1,de[p]+k)+1ll*(sz[p]-1)*min(de[p]-1,k));
  88. }
  89. return 0;
  90. }

upd 12.6:

其实这题可以也可以用长链剖分,因为我们可以设\(f_{x,j}\)为点\(x\)子树内深度为\(de_x+j\)的所有点的\((sz_x-1)\)之和,转移是\(f_{x,j}=\sum_{y=son_x}f_{y,j-1}\),这个可以长链剖分后优化,直接继承重儿子状态,暴力转移轻儿子状态

处理询问和上面类似,只不过这里要把\(f_{x,j}\)搞成后缀和形式

  1. // luogu-judger-enable-o2
  2. #include<bits/stdc++.h>
  3. #define LL long long
  4. #define il inline
  5. #define re register
  6. #define db double
  7. #define eps (1e-7)
  8. using namespace std;
  9. const int N=300000+10;
  10. const LL inf=(1ll<<50);
  11. il LL rd()
  12. {
  13. re LL x=0,w=1;re char ch=0;
  14. while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
  15. while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
  16. return x*w;
  17. }
  18. int to[N<<1],nt[N<<1],hd[N],tot=1;
  19. il void add(int x,int y)
  20. {
  21. ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
  22. ++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
  23. }
  24. int n,m,fa[N],sz[N],de[N],dpt[N],hson[N];
  25. int qk[N],qnt[N],qid[N],qhd[N],qt=1;
  26. il void qaq(int x,int k,int id){++qt,qk[qt]=k,qnt[qt]=qhd[x],qid[qt]=id,qhd[x]=qt;}
  27. LL an[N];
  28. void dfs1(int x)
  29. {
  30. sz[x]=1;
  31. for(int i=hd[x];i;i=nt[i])
  32. {
  33. int y=to[i];
  34. if(y==fa[x]) continue;
  35. fa[y]=x,dpt[y]=de[y]=de[x]+1,dfs1(y),sz[x]+=sz[y];
  36. if(dpt[hson[x]]<dpt[y]) hson[x]=y;
  37. dpt[x]=max(dpt[x],dpt[y]);
  38. }
  39. }
  40. LL *f[N],rbq[N<<1],*px=rbq+1;
  41. void dd(int x)
  42. {
  43. if(hson[x]) f[hson[x]]=f[x]+1,dd(hson[x]);
  44. for(int i=hd[x];i;i=nt[i])
  45. {
  46. int y=to[i];
  47. if(y==fa[x]||y==hson[x]) continue;
  48. f[y]=px,px+=dpt[y]-de[x]+1,dd(y);
  49. for(int i=dpt[y]-de[x]-1;i>=0;--i) f[x][i+1]+=f[y][i];
  50. }
  51. for(int i=qhd[x];i;i=qnt[i])
  52. {
  53. int k=qk[i],id=qid[i];
  54. an[id]=f[x][1]+1ll*(sz[x]-1)*min(de[x]-1,k);
  55. if(k+1<=dpt[x]-de[x]) an[id]-=f[x][k+1];
  56. }
  57. f[x][0]=f[x][1]+sz[x]-1;
  58. }
  59. int main()
  60. {
  61. n=rd(),m=rd();
  62. for(int i=1;i<n;i++) add(rd(),rd());
  63. de[1]=1;
  64. dfs1(1);
  65. for(int i=1;i<=m;++i)
  66. {
  67. int p=rd(),k=rd();
  68. qaq(p,k,i);
  69. }
  70. f[1]=px,px+=dpt[1];
  71. dd(1);
  72. for(int i=1;i<=m;++i) printf("%lld\n",an[i]);
  73. return 0;
  74. }

运行结果(O2):线段树合并 2022ms,长链剖分 942ms

后者不知道比前者高到哪去了,虽然不能和最优解谈笑风生

luogu P3899 [湖南集训]谈笑风生的更多相关文章

  1. 主席树 || 可持久化线段树 || BZOJ 3653: 谈笑风生 || Luogu P3899 [湖南集训]谈笑风生

    题面:P3899 [湖南集训]谈笑风生 题解: 我很喜欢这道题. 因为A是给定的,所以实质是求二元组的个数.我们以A(即给定的P)作为基点寻找答案,那么情况分两类.一种是B为A的父亲,另一种是A为B的 ...

  2. [Luogu P3899] [湖南集训]谈笑风生 (主席树)

    题面 传送门:https://www.luogu.org/problemnew/show/P3899 Solution 你们搞的这道题啊,excited! 这题真的很有意思. 首先,我们可以先理解一下 ...

  3. luogu P3899 [湖南集训]谈笑风生 线段树合并

    Code: #include<bits/stdc++.h> #define maxn 300002 #define ll long long using namespace std; vo ...

  4. P3899 [湖南集训]谈笑风生

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3653 https://www.luogu.org/problemnew/show/P38 ...

  5. 洛谷P3899 [湖南集训]谈笑风生(线段树合并)

    题意 题目链接 Sol 线段树合并板子题,目前我看到两种写法,分别是这样的. 前一种每次需要新建一个节点,空间是\(O(4nlogn)\) 后者不需要新建,空间是\(O(nlogn)\)(面向数据算空 ...

  6. Luogu 3899 [湖南集训]谈笑风生

    BZOJ 3653权限题. 这题方法很多,但我会的不多…… 给定了$a$,我们考虑讨论$b$的位置: 1.$b$在$a$到根的链上,那么这样子$a$的子树中的每一个结点(除了$a$之外)都是可以成为$ ...

  7. P3899 [湖南集训]谈笑风生 主席树

    #include<iostream> #include<string.h> #include<algorithm> #include<stdio.h> ...

  8. 【洛谷 P3899】 [湖南集训]谈笑风生 (主席树)

    题目链接 容易发现\(a,b,c\)肯定是在一条直链上的. 定义\(size(u)\)表示以\(u\)为根的子树大小(不包括\(u\)) 分两种情况, 1.\(b\)是\(a\)的祖先,对答案的贡献是 ...

  9. bzoj 3653 [湖南集训]谈笑风生

    题目描述 设 T 为一棵有根树,我们做如下的定义: • 设 a 和 b 为 T 中的两个不同节点.如果 a 是 b 的祖先,那么称"a 比 b 不知道高明到哪里去了". • 设 a ...

随机推荐

  1. Manjaro更新出现冲突

    ➜ ~ sudo pacman -Syyu :: Synchronizing package databases... core 147.5 KiB 1378K/s 00:00 [########## ...

  2. MVC Razor

    1.@....    相当于<%=...%> 2.@{}  相当于<%%>,遇到无法自动转换的,需要在前面加@: 3.@()  将某一段代码当做C#代码 4.表单提交name值 ...

  3. A1127. ZigZagging on a Tree

    Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree can ...

  4. win32-api: 让 static 控件中的水平横行,垂直居中。

    CreateWindowEx(....., SS_CENTER | SS_CENTERIMAGE); SS_CENTER  能让文字水平居中. SS_CENTERIMAGE 能让文字垂直居中. htt ...

  5. 跟我一起用node-express搭建一个小项目(mongodb)[二]

    我的小项目主要是会用到MongoDB. 呵呵,我也是现学现卖. 都说小公司十八般武艺样样稀疏,没有办法啊! 兵来兵挡,将来将挡!自己是个兵呢?还是一个将呢! 没有公司培养,就自己培养自己呗.差的远一点 ...

  6. marks学习2

    控件的大小单位用dp  控件的高度和宽度 sp字体的单位 控件的字体的大小.可缩放字体. 内边距 padding控件的边缘到控件内荣的距离

  7. halcon几何变换(仿射变换)

    旋转.平移.镜像.缩放.斜切,可参考https://blog.csdn.net/machaoyu86/article/details/51182473 仿射变换前,需要获得仿射变换矩阵. 关于shap ...

  8. day14-jdbc案例(简单的curd&分页)

    回顾: mvc jsp的设计模式1: jsp+javabean jsp的设计模式2: jsp+javabean+servlet jsp:展示数据 javabean:封装数据 封装对数据的访问 serv ...

  9. HTTP常用头部信息

    下面用例子的形式来记录下常用的一些Http头部信息 Request Header: GET /sample.Jsp HTTP/1.1  //请求行 Host: www.uuid.online/  // ...

  10. 数据预处理:独热编码(One-Hot Encoding)

    python机器学习-sklearn挖掘乳腺癌细胞( 博主亲自录制) 网易云观看地址 https://study.163.com/course/introduction.htm?courseId=10 ...