直入主题:

学习线段树合并.....

从名字就能看出,这个东西要合并线段树.....

线段树怎么能合并呢......

暴力合就行了啊......

一次从上往下的遍历,把所有的节点信息暴力合并,然后就没有然后了.....

有两种合并方法:

一、动态开点

就是主席树那样的模式(可持久化了),新开一个点记录新的节点信息,但是空间~巨~大~无~比~

然后可能需要删除节点(以前的,既然合并了,就不需要旧的了233....)

二、静态开点(口胡的)

像启发式合并那样,直接把a的信息全加到b上(虽然没有任何启发式),但是可能破坏a树的形态

于是放一发模板题(本蒻第一次封装结构体233)

(感觉就是主席树233)

首先,思路树上差分,但是具体怎么玩呢?

一个暴力的思路:

对于每一个给定的补给点,建一棵权值线段树,其他的点也有线段树但是是空树,然后在差分的时候直接把所有的点给合并起来,最后统计答案。

线段树维护的是最值。

注意的是:差分:a+1,b+1,lca-1,lca的父节点+1,这个父节点是为了消除向上的影响,只维护路径上的值。

注释在代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int n,m;
struct edge
{int to,next;
}e[maxn];
int head[maxn],cnt;
inline void addedge(int from,int to)
{e[++cnt].next=head[from];e[cnt].to=to;head[from]=cnt;
}
int dep[maxn];
int f[maxn][40];
int dfs(int u,int fa)
{dep[u]=dep[fa]+1;for(int i=head[u];i;i=e[i].next){int v=e[i].to;if(v==fa)continue;dfs(v,u);f[v][0]=u;}
}
int rt[maxn];
struct segtree//第一次封装结构体
{int lc[maxn*40],rc[maxn*40],ma[maxn*40],id[maxn*40],root=0;void pushup(int p)//更新最值{if(ma[lc[p]]>=ma[rc[p]]){ma[p]=ma[lc[p]];id[p]=id[lc[p]];//值得注意的是:这个id是记录答案的,所以要一起更新}else{ma[p]=ma[rc[p]];id[p]=id[rc[p]];}}int merge(int a,int b,int l,int r){if(!a||!b)//如果一个是空的,那就返回有值的那个节点return a+b;if(l==r){ma[a]=ma[a]+ma[b],id[a]=l;//如果是叶节点就更新return a;}int mid=l+r>>1;lc[a]=merge(lc[a],lc[b],l,mid);//向下合并rc[a]=merge(rc[a],rc[b],mid+1,r);//向下合并pushup(a);//记得更新return a;}void insert(int &x,int l,int r,int p,int k){if(x==0)x=++root;//十分类似主席树的插入if(l==r){id[x]=l;ma[x]+=k;return;}int mid=l+r>>1;if(p<=mid)insert(lc[x],l,mid,p,k);else    insert(rc[x],mid+1,r,p,k);pushup(x);}
}T;
int lca(int a,int b)//平淡无奇的lca
{if(dep[a]<dep[b])swap(a,b);for(int i=20;i>=0;i--){if(dep[b]<=dep[a]-(1<<i))a=f[a][i];}if(a==b)return a;for(int i=20;i>=0;i--){if(f[a][i]!=f[b][i]){a=f[a][i];b=f[b][i];}}return f[a][0];
}
int ans[maxn];
void dfsans(int u,int fa)
{for(int i=head[u];i;i=e[i].next){int v=e[i].to;if(v==fa)continue;dfsans(v,u);rt[u]=T.merge(rt[u],rt[v],1,100000);//合并}ans[u]=T.id[rt[u]];//更新答案if(T.ma[rt[u]]==0)ans[u]=0;//记得特判0的情况
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addedge(x,y);addedge(y,x);}dfs(1,0);for(int i=1;i<=30;i++){for(int j=1;j<=n;j++){f[j][i]=f[f[j][i-1]][i-1];}}for(int i=1;i<=m;i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);int u=lca(x,y);T.insert(rt[u],1,100000,z,-1);T.insert(rt[x],1,100000,z,1);T.insert(rt[y],1,100000,z,1);T.insert(rt[f[u][0]],1,100000,z,-1);}dfsans(1,0);for(int i=1;i<=n;i++)printf("%d\n",ans[i]);return 0;
}

(完)

转载于:https://www.cnblogs.com/ajmddzp/p/11625737.html

线段树合并学习笔记(P4556)相关推荐

  1. 线段树分裂与合并 ---- 树上差分 P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并

    题目链接 解题思路: 首先题目是对u,vu,vu,v这两条路径上面添加一个zzz,然后运用树上点的差分思想,对于分发路径u,vu,vu,v,我们在uuu上+1+1+1,在vvv上+1+1+1,在lca ...

  2. 【线段树合并】解题报告:luogu P4556雨天的尾巴 (树上对点差分 + 动态开点 + 线段树合并)线段树合并模板离线/在线详解

    题目链接:雨天的尾巴 本题本身是一个非常简单的一道树上差分的模板题,但是由于变态的数据范围,我们直接用数组是存不下的(本来使用一颗普通的线段树直接维护最大值即可.但是本题的空间只有128MB,直接按照 ...

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

    题目链接:点击查看 题目大意:给出一棵树,再给出 m 次操作,每次操作会选择两个点 ( x , y ) ,使得这条路径上的所有点的种类 z 加一,最后问每个点的哪个种类出现的频率最高,若多个种类出现频 ...

  4. BZOJ2212——线段树合并

    学习线段树合并,以这道题为契机 多谢这篇博客 这里是通过对线段树合并时,顺手统计了对于一颗子树内,是否反转两种情况的逆序对数 这里只对代码进行详细分析,见注解好了 1 #include<cstd ...

  5. 线段树合并(四道例题)

    顾名思义,就是合并两个同构(就是维护的区间长度一样)线段树,其实也没啥比较nb的算法,就是一个一个节点的合并,但是如果在n个要合并的线段树里,如果一共有m个元素,则配合动态开点,复杂度会均摊成一个惊人 ...

  6. 珂朵莉树/ODT 学习笔记

    珂朵莉树/ODT 学习笔记 起源自 CF896C.珂朵莉yyds! 核心思想 把值相同的区间合并成一个结点保存在 set 里面. 用处 骗分.只要是有区间赋值操作的数据结构题都可以用来骗分.在数据随机 ...

  7. 线段树合并:从入门到放弃

    感谢这篇博客(这里跳转)以及邱宇大神的讲解,我也算作入门(自闭)了. 需要掌握的前置知识点:动态开点线段树.权值线段树. 一.合并思想 线段树合并,就是指建立一颗新的线段树,保存原有的两颗线段树的信息 ...

  8. 线段树合并与分裂维护树上最长上升子序列 + 点分治删点 ---- 2021 牛客多校第一场 C - Cut the tree(详解)

    题目大意: 给你一个树,树上每个点都有一个权值valnodeval_{node}valnode​,路径(u,v)(u,v)(u,v) 上所有点按顺序有序序列,令f(u,v)f(u,v)f(u,v)是这 ...

  9. 【BZOJ-3681】Arietta 网络流 + 线段树合并

    3681: Arietta Time Limit: 20 Sec  Memory Limit: 64 MB Submit: 182  Solved: 70 [Submit][Status][Discu ...

  10. BZOJ3526[Poi2014]Card——线段树合并

    题目描述 有n张卡片在桌上一字排开,每张卡片上有两个数,第i张卡片上,正面的数为a[i],反面的数为b[i].现在,有m个熊孩子来破坏你的卡片了! 第i个熊孩子会交换c[i]和d[i]两个位置上的卡片 ...

最新文章

  1. nodejs 各种插件
  2. SDK与API的联系与区别
  3. leetcode:Plus One
  4. OA办公系统的核心-工作流
  5. Docker底层技术
  6. Linux 内核链表 【转】
  7. HttpClient在传参和返回结果的中文乱码问题
  8. 项目案例:qq数据库管理_2小时元项目:项目管理您的数据科学学习
  9. 如何找素材,设计师必备技能
  10. kali linux之Meterpreter
  11. Excel VBA简单使用——数据缺失处理
  12. UNISON文件同步
  13. Python如何打印出26个大写字母和26个小写字母
  14. TextView字体加粗
  15. 阿里云centos环境之vsftpd安装(十五)
  16. 养成良好的编程习惯-一个库一个文件夹
  17. python实现千牛客服自动回复语_千牛自动回复语大全
  18. 孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9并使用pydocx模块将结果写入word文档...
  19. Cocos Creator 3D使用腾讯云游戏联机对战引擎(MGOBE)
  20. simulink仿真之比较产生阶梯波

热门文章

  1. 新浪微博错误提示代码
  2. 详解 Win8 KMS 激活原理_-Chaz-_新浪博客
  3. linux下火狐浏览器如何安装flash插件
  4. 什么是表压?什么是绝压?表压和绝压什么关系?
  5. 网络电话是如何实现打到普通话机上的?
  6. 一元云购CMS微信分享打不开解决办法
  7. linux运行proxmark3,Linux 下编译使用Proxmark3
  8. 电脑上计算机三个键盘的使用方法,干货:全方面介绍电脑键盘各键功能与组合键使用方法...
  9. Pandas的介绍和使用
  10. EXSi虚拟机缺少vmdk文件报错问题