线段树合并学习笔记(P4556)
直入主题:
学习线段树合并.....
从名字就能看出,这个东西要合并线段树.....
线段树怎么能合并呢......
暴力合就行了啊......
一次从上往下的遍历,把所有的节点信息暴力合并,然后就没有然后了.....
有两种合并方法:
一、动态开点
就是主席树那样的模式(可持久化了),新开一个点记录新的节点信息,但是空间~巨~大~无~比~
然后可能需要删除节点(以前的,既然合并了,就不需要旧的了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)相关推荐
- 线段树分裂与合并 ---- 树上差分 P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并
题目链接 解题思路: 首先题目是对u,vu,vu,v这两条路径上面添加一个zzz,然后运用树上点的差分思想,对于分发路径u,vu,vu,v,我们在uuu上+1+1+1,在vvv上+1+1+1,在lca ...
- 【线段树合并】解题报告:luogu P4556雨天的尾巴 (树上对点差分 + 动态开点 + 线段树合并)线段树合并模板离线/在线详解
题目链接:雨天的尾巴 本题本身是一个非常简单的一道树上差分的模板题,但是由于变态的数据范围,我们直接用数组是存不下的(本来使用一颗普通的线段树直接维护最大值即可.但是本题的空间只有128MB,直接按照 ...
- 洛谷 - P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并(树上差分+线段树合并)
题目链接:点击查看 题目大意:给出一棵树,再给出 m 次操作,每次操作会选择两个点 ( x , y ) ,使得这条路径上的所有点的种类 z 加一,最后问每个点的哪个种类出现的频率最高,若多个种类出现频 ...
- BZOJ2212——线段树合并
学习线段树合并,以这道题为契机 多谢这篇博客 这里是通过对线段树合并时,顺手统计了对于一颗子树内,是否反转两种情况的逆序对数 这里只对代码进行详细分析,见注解好了 1 #include<cstd ...
- 线段树合并(四道例题)
顾名思义,就是合并两个同构(就是维护的区间长度一样)线段树,其实也没啥比较nb的算法,就是一个一个节点的合并,但是如果在n个要合并的线段树里,如果一共有m个元素,则配合动态开点,复杂度会均摊成一个惊人 ...
- 珂朵莉树/ODT 学习笔记
珂朵莉树/ODT 学习笔记 起源自 CF896C.珂朵莉yyds! 核心思想 把值相同的区间合并成一个结点保存在 set 里面. 用处 骗分.只要是有区间赋值操作的数据结构题都可以用来骗分.在数据随机 ...
- 线段树合并:从入门到放弃
感谢这篇博客(这里跳转)以及邱宇大神的讲解,我也算作入门(自闭)了. 需要掌握的前置知识点:动态开点线段树.权值线段树. 一.合并思想 线段树合并,就是指建立一颗新的线段树,保存原有的两颗线段树的信息 ...
- 线段树合并与分裂维护树上最长上升子序列 + 点分治删点 ---- 2021 牛客多校第一场 C - Cut the tree(详解)
题目大意: 给你一个树,树上每个点都有一个权值valnodeval_{node}valnode,路径(u,v)(u,v)(u,v) 上所有点按顺序有序序列,令f(u,v)f(u,v)f(u,v)是这 ...
- 【BZOJ-3681】Arietta 网络流 + 线段树合并
3681: Arietta Time Limit: 20 Sec Memory Limit: 64 MB Submit: 182 Solved: 70 [Submit][Status][Discu ...
- BZOJ3526[Poi2014]Card——线段树合并
题目描述 有n张卡片在桌上一字排开,每张卡片上有两个数,第i张卡片上,正面的数为a[i],反面的数为b[i].现在,有m个熊孩子来破坏你的卡片了! 第i个熊孩子会交换c[i]和d[i]两个位置上的卡片 ...
最新文章
- nodejs 各种插件
- SDK与API的联系与区别
- leetcode:Plus One
- OA办公系统的核心-工作流
- Docker底层技术
- Linux 内核链表 【转】
- HttpClient在传参和返回结果的中文乱码问题
- 项目案例:qq数据库管理_2小时元项目:项目管理您的数据科学学习
- 如何找素材,设计师必备技能
- kali linux之Meterpreter
- Excel VBA简单使用——数据缺失处理
- UNISON文件同步
- Python如何打印出26个大写字母和26个小写字母
- TextView字体加粗
- 阿里云centos环境之vsftpd安装(十五)
- 养成良好的编程习惯-一个库一个文件夹
- python实现千牛客服自动回复语_千牛自动回复语大全
- 孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9并使用pydocx模块将结果写入word文档...
- Cocos Creator 3D使用腾讯云游戏联机对战引擎(MGOBE)
- simulink仿真之比较产生阶梯波