[BZOJ3307] 雨天的尾巴(树上差分+线段树合并)

题面

给出一棵N个点的树,M次操作在链上加上某一种类别的物品,完成所有操作后,要求询问每个点上最多物品的类型。

N, M≤100000

分析

考虑树上差分。对于每条链(x,y),我们在x,y打一个+标记,lca(x,y)和lca(x,y)的父亲打一个-标记。然后在每个节点建立一棵权值线段树,下标v维护物品v的个数。如果有物品v,就把下标为v的位置+1,如果有-标记,就-1.线段树push_up的时候可以计算出最多物品的类型

然后从下往上线段树合并,合并到某个节点的时候就更新该节点的答案。

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #define maxn 100000
  5. #define maxlogn 60
  6. using namespace std;
  7. int n,m;
  8. struct edge{
  9. int from;
  10. int to;
  11. int next;
  12. }E[maxn*2+5];
  13. int sz=1;
  14. int head[maxn+5];
  15. void add_edge(int u,int v){
  16. sz++;
  17. E[sz].from=u;
  18. E[sz].to=v;
  19. E[sz].next=head[u];
  20. head[u]=sz;
  21. }
  22. int deep[maxn+5];
  23. int anc[maxn+5][maxlogn+5];
  24. void dfs1(int x,int fa){
  25. deep[x]=deep[fa]+1;
  26. anc[x][0]=fa;
  27. for(int i=1;i<=maxlogn;i++) anc[x][i]=anc[anc[x][i-1]][i-1];
  28. for(int i=head[x];i;i=E[i].next){
  29. int y=E[i].to;
  30. if(y!=fa){
  31. dfs1(y,x);
  32. }
  33. }
  34. }
  35. int lca(int x,int y){
  36. if(deep[x]<deep[y]) swap(x,y);
  37. for(int i=maxlogn;i>=0;i--){
  38. if(deep[anc[x][i]]>=deep[y]){
  39. x=anc[x][i];
  40. }
  41. }
  42. if(x==y) return x;
  43. for(int i=maxlogn;i>=0;i--){
  44. if(anc[x][i]!=anc[y][i]){
  45. x=anc[x][i];
  46. y=anc[y][i];
  47. }
  48. }
  49. return anc[x][0];
  50. }
  51. struct segment_tree{
  52. #define lson(x) (tree[x].ls)
  53. #define rson(x) (tree[x].rs)
  54. struct node{
  55. int ls;
  56. int rs;
  57. int cnt;
  58. int id;
  59. }tree[maxn*maxlogn+5];
  60. int ptr;
  61. void push_up(int x){
  62. if(tree[lson(x)].cnt>tree[rson(x)].cnt){
  63. tree[x].cnt=tree[lson(x)].cnt;
  64. tree[x].id=tree[lson(x)].id;
  65. }else if(tree[lson(x)].cnt==tree[rson(x)].cnt){
  66. tree[x].cnt=tree[lson(x)].cnt;
  67. tree[x].id=min(tree[lson(x)].id,tree[rson(x)].id);
  68. }else{
  69. tree[x].cnt=tree[rson(x)].cnt;
  70. tree[x].id=tree[rson(x)].id;
  71. }
  72. }
  73. void update(int &x,int upos,int uval,int l,int r){
  74. if(!x) x=++ptr;
  75. if(l==r){
  76. tree[x].cnt+=uval;
  77. tree[x].id=l;
  78. return;
  79. }
  80. int mid=(l+r)>>1;
  81. if(upos<=mid) update(tree[x].ls,upos,uval,l,mid);
  82. else update(tree[x].rs,upos,uval,mid+1,r);
  83. push_up(x);
  84. }
  85. int merge(int x,int y,int l,int r){
  86. if(!x||!y) return x+y;
  87. if(l==r){
  88. tree[x].cnt+=tree[y].cnt;
  89. tree[x].id=l;
  90. return x;
  91. }
  92. int mid=(l+r)>>1;
  93. tree[x].ls=merge(tree[x].ls,tree[y].ls,l,mid);
  94. tree[x].rs=merge(tree[x].rs,tree[y].rs,mid+1,r);
  95. push_up(x);
  96. return x;
  97. }
  98. }T;
  99. int root[maxn+5];
  100. int ans[maxn+5];
  101. int maxz;
  102. struct query{
  103. int x;
  104. int y;
  105. int z;
  106. }q[maxn+5];
  107. void dfs2(int x,int fa){
  108. for(int i=head[x];i;i=E[i].next){
  109. int y=E[i].to;
  110. if(y!=fa){
  111. dfs2(y,x);
  112. root[x]=T.merge(root[x],root[y],1,maxz);
  113. }
  114. }
  115. if(T.tree[root[x]].cnt) ans[x]=T.tree[root[x]].id;
  116. else ans[x]=0;
  117. }
  118. int main(){
  119. int u,v;
  120. scanf("%d %d",&n,&m);
  121. for(int i=1;i<n;i++){
  122. scanf("%d %d",&u,&v);
  123. add_edge(u,v);
  124. add_edge(v,u);
  125. }
  126. dfs1(1,0);
  127. maxz=0;
  128. for(int i=1;i<=m;i++){
  129. scanf("%d %d %d",&q[i].x,&q[i].y,&q[i].z);
  130. maxz=max(q[i].z,maxz);
  131. }
  132. for(int i=1;i<=m;i++){
  133. int x=q[i].x,y=q[i].y,z=q[i].z,lc=lca(x,y);
  134. T.update(root[x],z,1,1,maxz);
  135. T.update(root[y],z,1,1,maxz);
  136. T.update(root[lc],z,-1,1,maxz);
  137. T.update(root[anc[lc][0]],z,-1,1,maxz);
  138. }
  139. dfs2(1,0);
  140. for(int i=1;i<=n;i++){
  141. printf("%d\n",ans[i]);
  142. }
  143. }

[BZOJ3307] 雨天的尾巴(树上差分+线段树合并)的更多相关文章

  1. BZOJ 3307 雨天的尾巴 (树上差分+线段树合并)

    题目大意:给你一棵树,树上一共n个节点,共m次操作,每次操作给一条链上的所有节点分配一个权值,求所有节点被分配到所有的权值里,出现次数最多的权值是多少,如果出现次数相同就输出最小的. (我辣鸡bzoj ...

  2. bzoj3307 雨天的尾巴 题解(线段树合并+树上差分)

    Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后,每个点存放最多的是哪种物品. Input ...

  3. [Luogu5327][ZJOI2019]语言(树上差分+线段树合并)

    首先可以想到对每个点统计出所有经过它的链的并所包含的点数,然后可以直接得到答案.根据实现不同有下面几种方法.三个log:假如对每个点都存下经过它的链并S[x],那么每新加一条路径进来的时候,相当于在路 ...

  4. 2018.08.28 洛谷P4556 [Vani有约会]雨天的尾巴(树上差分+线段树合并)

    传送门 要求维护每个点上出现次数最多的颜色. 对于每次修改,我们用树上差分的思想,然后线段树合并统计答案就行了. 注意颜色很大需要离散化. 代码: #include<bits/stdc++.h& ...

  5. bzoj 3307: 雨天的尾巴【树剖lca+树上差分+线段树合并】

    这居然是我第一次写线段树合并--所以我居然在合并的时候加点结果WAWAWAMLEMLEMLE--!ro的时候居然直接指到la就行-- 树上差分,每个点建一棵动态开点线段树,然后统计答案的时候合并即可 ...

  6. P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并 (树上差分+线段树合并)

    显然的树上差分问题,最后要我们求每个点数量最多的物品,考虑对每个点建议线段树,查询子树时将线段树合并可以得到答案. 用动态开点的方式建立线段树,注意离散化. 1 #include<bits/st ...

  7. 【bzoj3307】雨天的尾巴 权值线段树合并

    题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y,对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入 第一行数字N,M接下来 ...

  8. Luogu5327 ZJOI2019语言(树上差分+线段树合并)

    暴力树剖做法显然,即使做到两个log也不那么优美. 考虑避免树剖做到一个log.那么容易想到树上差分,也即要对每个点统计所有经过他的路径产生的总贡献(显然就是所有这些路径端点所构成的斯坦纳树大小),并 ...

  9. [NOIP2016]天天爱跑步(树上差分+线段树合并)

    将每个人跑步的路径拆分成x->lca,lca->y两条路径分别考虑: 对于在点i的观察点,这个人(s->t)能被观察到的充要条件为: 1.直向上的路径:w[i]=dep[s]-dep ...

随机推荐

  1. ln创建软链接方式

    ln -s 目标文件 软链接

  2. 下载-MS SQL Server 2005(大全版)含开发人员版、企业版、标准版【转】

    中文名称:微软SQL Server 2005 英文名称:MS SQL Server 2005资源类型:ISO版本:开发人员版.企业版.标准版发行时间:2006年制作发行:微软公司地区:大陆语言:普通话 ...

  3. Git分支操作步骤

    学习操作Git分支,具体如下: - 查看分支 - 创建分支 - 切换分支 - 合并分支 - 解决分支的冲突 方案: Git支持按功能模块,时间,版本等标准创建分支; 分支可以让开发分多条主线同时进行, ...

  4. python基础--内置函数filter,reduce

    movie_people=["sb+_alex","sb_wupeiqi","han"] # def filter_test(array): ...

  5. Python开发—打包成exe

    pychaim下PyInstaller 打包 python程序 使用PyCharm开发python Pyinstaller打包jieba项目相关解决方案 Python打包成exe 一.安装pyinst ...

  6. paste 合并文件

    1.命令功能 paste  用于合并文件的列,把每个文件以列对列的方式,一列列地加以合并. 2.语法格式 paste  option  file 参数选项 参数 参数说明 -d 指定间隔符合并文件(默 ...

  7. CF3D Least Cost Bracket Sequence(2500的实力贪心...

    哎,昨天一直在赶课设..没有写 最近听了一些人的建议,停止高级算法的学习,开始刷cf. 目前打算就是白天懒得背电脑的话,系统刷一遍蓝书紫书白书之类的(一直没系统刷过),回宿舍再上机吧. https:/ ...

  8. [python 学习] argparse模块

    https://docs.python.org/3/library/argparse.html#module-argparse

  9. Sentinel 1.7.0 发布,支持 Envoy 集群流量控制

    流控降级中间件Sentinel 1.7.0版本正式发布,引入了 Envoy 集群流量控制支持.properties 文件配置.Consul/Etcd/Spring Cloud Config 动态数据源 ...

  10. SecondModel 实现类

    package com.test.mvp.mvpdemo.mvp.v6.model; import com.test.mvp.mvpdemo.mvp.v6.SecondContract;import ...