直入主题:

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

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

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

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

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

有两种合并方法:

一、动态开点

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

然后可能需要删除节点(以前的,既然合并了,就不需要旧的了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+;
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][];
int dfs(int u,int fa)
{
dep[u]=dep[fa]+;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa)
continue;
dfs(v,u);
f[v][]=u;
}
}
int rt[maxn];
struct segtree//第一次封装结构体
{
int lc[maxn*],rc[maxn*],ma[maxn*],id[maxn*],root=;
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>>;
lc[a]=merge(lc[a],lc[b],l,mid);//向下合并
rc[a]=merge(rc[a],rc[b],mid+,r);//向下合并
pushup(a);//记得更新
return a;
}
void insert(int &x,int l,int r,int p,int k)
{
if(x==)
x=++root;//十分类似主席树的插入
if(l==r)
{
id[x]=l;
ma[x]+=k;
return;
}
int mid=l+r>>;
if(p<=mid)insert(lc[x],l,mid,p,k);
else insert(rc[x],mid+,r,p,k);
pushup(x);
}
}T;
int lca(int a,int b)//平淡无奇的lca
{
if(dep[a]<dep[b])
swap(a,b);
for(int i=;i>=;i--)
{
if(dep[b]<=dep[a]-(<<i))
a=f[a][i];
}
if(a==b)
return a;
for(int i=;i>=;i--)
{
if(f[a][i]!=f[b][i])
{
a=f[a][i];
b=f[b][i];
}
}
return f[a][];
}
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],,);//合并
}
ans[u]=T.id[rt[u]];//更新答案
if(T.ma[rt[u]]==)
ans[u]=;//记得特判0的情况
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
dfs(,);
for(int i=;i<=;i++)
{
for(int j=;j<=n;j++)
{
f[j][i]=f[f[j][i-]][i-];
}
}
for(int i=;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
int u=lca(x,y);
T.insert(rt[u],,,z,-);
T.insert(rt[x],,,z,);
T.insert(rt[y],,,z,);
T.insert(rt[f[u][]],,,z,-);
}
dfsans(,);
for(int i=;i<=n;i++)
printf("%d\n",ans[i]);
return ;
}

(完)

线段树合并学习笔记(P4556)的更多相关文章

  1. P4556 [Vani有约会]雨天的尾巴(线段树合并+lca)

    P4556 [Vani有约会]雨天的尾巴 每个操作拆成4个进行树上差分,动态开点线段树维护每个点的操作. 离线处理完向上合并就好了 luogu倍增lca被卡了5分.....于是用rmq维护.... 常 ...

  2. P4556 [Vani有约会]雨天的尾巴 (线段树合并)

    P4556 [Vani有约会]雨天的尾巴 题意: 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋 ...

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

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

  4. P4556 [Vani有约会]雨天的尾巴(线段树合并)

    传送门 一道线段树合并 首先不难看出树上差分 我们把每一次修改拆成四个,在\(u,v\)分别放上一个,在\(lca\)和\(fa[lca]\)各减去一个,那么只要统计一下子树里的总数即可 然而问题就在 ...

  5. 线段树合并&&启发式合并笔记

    这俩东西听起来很高端,实际上很好写,应用也很多~ 线段树合并 线段树合并,顾名思义,就是建立一棵新的线段树保存原有的两颗线段树的信息. 考虑如何合并,对于一个结点,如果两颗线段树都有此位置的结点,则直 ...

  6. P4556 雨天的尾巴 线段树合并

    使用线段树合并,每个节点维护一棵权值线段树,下标为救济粮种类,区间维护数量最多的救济粮编号(下标).所以每个节点答案即为\(tre[rot[x]]\). 然后运用树上点的差分思想,对于分发路径\(u, ...

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

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

  8. Subtree Minimum Query CodeForces - 893F (线段树合并+线段树动态开点)

    题目链接:https://cn.vjudge.net/problem/CodeForces-893F 题目大意:给你n个点,每一个点有权值,然后这n个点会构成一棵树,边权为1.然后有q次询问,每一次询 ...

  9. 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)

    线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...

随机推荐

  1. cocos2d-x C++ 工程初探

    经过较为繁琐的环境搭建后,我们终于运行出了一个helloworld窗口,可以正式上手cocos了 现在我们就从改代码开始玩起 窗口 我们之前讲到AppDelegate类是程序的入口,所以和窗口有关的设 ...

  2. c语言作业04

    这个作业属于哪个课程 C语言程序设计Ⅱ 这个作业要求在哪里 (作业要求)[https://edu.cnblogs.com/campus/zswxy/SE2019-1/homework/9773] 我在 ...

  3. 浅谈json web token及应用

    Json Web Token (JWT),是一个非常轻巧的规范,这个规范允许在网络应用环境间客户端和服务器间较安全的传递信息.该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO) ...

  4. http服务端架构演进

    摘要 在详解http报文相关文章中我们介绍了http协议是如何工作的,那么构建一个真实的网站还需要引入组件呢?一些常见的名词到底是什么含义呢? 什么叫正向代理,什么叫反向代理 服务代理与负载均衡的差别 ...

  5. Bran的内核开发教程(bkerndev)-05 打印到屏幕

    打印到屏幕   现在, 我们需要尝试打印到屏幕上.为此, 我们需要管理屏幕滚动, 如果能允许使用不同的颜色就更好了.好在VGA视频卡为我们提供了一片内存空间, 允许同时写入属性字节和字符字节对, 可以 ...

  6. 代码审计-EasyCMS

    cms来源AWD线下攻防平台题目.  链接:https://pan.baidu.com/s/1eUkyRspQmsv-0fIBby8ZlQ  提取码:tywa 失效可以联系我   0x01 文件上传漏 ...

  7. shark恒破解笔记6-摆脱NAG

    1.打开软件后,发现是未注册,然后点击关闭按钮,会弹出窗口 我们的目的就是为了能够去掉这个弹窗. 2.对这个程序进行查壳,没有什么发现 3.载入OD里面,F9运行起来,随后切换到程序主界面点击关闭按钮 ...

  8. 创建优化的Go镜像文件以及踩过的坑

    在Docker上创建Go镜像文件并不困难,但建立的文件很大,接近1G,使用起来不太方便.Docker镜像的一个主要难题就是如何优化,创建小的镜像.我们可以用多级构建的方法来创建Docker镜像文件,它 ...

  9. VSCode 配置 Python 开发环境

    一.环境准备 首先需要先安装好 Python 和 VSCode, 下载地址如下 VSCode Python 二.安装 Python 扩展 首先在VSCode上安装 Python 扩展,如图: 三.新建 ...

  10. java web项目下的lib和build path 中jar包问题解惑

    一.build path&WEB-INFO/lib介绍 build path:可以说是引用: WEB-INFO/lib:可以说是固定在一个地方: eclipse编译项目的时候是根据build ...