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

直入主题: 学习线段树合并..... 从名字就能看出,这个东西要合并线段树..... 线段树怎么能合并呢...... 暴力合就行了啊...... 一次从上往下的遍历,把所有的节点信息暴力合并,然后就没有然后了..... 有两种合并方法: 一.动态开点 就是主席树那样的模式(可持久化了),新开一个点记录新的节点信息,但是空间~巨~大~无~比~ 然后可能需要删除节点(以前的,既然合并了,就不需要旧的了233....) 二.静态开点(口胡的) 像启发式合并那样,直接把a的信息全加到b上(虽然没有任何启…
P4556 [Vani有约会]雨天的尾巴 每个操作拆成4个进行树上差分,动态开点线段树维护每个点的操作. 离线处理完向上合并就好了 luogu倍增lca被卡了5分.....于是用rmq维护.... 常数很大,被bzoj卡了(但是我不想改了) #include<iostream> #include<cstdio> #include<cstring> #include<vector> #define ri register int using namespace…
P4556 [Vani有约会]雨天的尾巴 题意: 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮. 然后深绘里想知道,当所有的救济粮发放完毕后,每座房子里存放的最多的是哪种救济粮. 题解: 树链剖分的写法很明显了,维护一个max即可 讲一下线段树合并的写法 区间更新用单点更新和差分来代替,求一个LCA,x->y的更新即可用在点x+1,点y+1,点lca(x,y)-1,点fa(lc…
传送门 要求维护每个点上出现次数最多的颜色. 对于每次修改,我们用树上差分的思想,然后线段树合并统计答案就行了. 注意颜色很大需要离散化. 代码: #include<bits/stdc++.h> #define N 100005 #define Max 100000 using namespace std; inline int read(){ int ans=0; char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigi…
传送门 一道线段树合并 首先不难看出树上差分 我们把每一次修改拆成四个,在\(u,v\)分别放上一个,在\(lca\)和\(fa[lca]\)各减去一个,那么只要统计一下子树里的总数即可 然而问题就在于怎么统计.直接暴力肯定是要咕咕的,那么线段树合并就派上用场了 总之就是每个点开一个动态开点线段树,然后一遍dfs,让它的所有儿子的线段树合并到它这里 我按以前的写法不知为什么写挂了--然后换抄了种写法还是挂--后来发现是写抄的时候没有注意合并的顺序-- //minamoto #include<bi…
这俩东西听起来很高端,实际上很好写,应用也很多~ 线段树合并 线段树合并,顾名思义,就是建立一棵新的线段树保存原有的两颗线段树的信息. 考虑如何合并,对于一个结点,如果两颗线段树都有此位置的结点,则直接合并两结点的信息(如维护最大值则取max,维护和则相加),然后递归处理左右子树: 若只有一个有,直接返回即可. 这样子做时间复杂度取决于重合节点个数,一次最坏复杂度是$O(nlogn)$,因为满二叉树的结点数是$O(n)$,对每个结点进行处理是$O(logn)$,但是实际应用中需要合并的两颗树重合…
使用线段树合并,每个节点维护一棵权值线段树,下标为救济粮种类,区间维护数量最多的救济粮编号(下标).所以每个节点答案即为\(tre[rot[x]]\). 然后运用树上点的差分思想,对于分发路径\(u,v\),我们在\(u\)上+1,在\(v\)+1,在\(lca(u,v)\)处-1,在\(fa(lca)\)处-1,最后统计时自底向上做树上前缀和.线段树合并即得当前节点信息. 需要注意的是,在合并时可能会出现\(tre[rot[x]]\)不为\(0\),但是\(sum[rot[x]]\)为\(0\…
显然的树上差分问题,最后要我们求每个点数量最多的物品,考虑对每个点建议线段树,查询子树时将线段树合并可以得到答案. 用动态开点的方式建立线段树,注意离散化. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 1e5 + 10; 4 struct node { 5 int lc, rc, dat, pos;//dat记录最多的物品的次数,pos记录位置 6 }tr[N * 20 * 4]; 7 int head[N]…
题目链接:https://cn.vjudge.net/problem/CodeForces-893F 题目大意:给你n个点,每一个点有权值,然后这n个点会构成一棵树,边权为1.然后有q次询问,每一次询问包括t1和t2.让你找出以t1为根节点的树上,距离t1不超过t2的节点,最小的点权值. 每一次的t1是(上次询问的结果+t1)%n+1,t2是(上次询问的结果+t1).所以就必须的强制在线了. 具体思路:线段树合并,通过dfs序进行遍历,以每一个点的深度作为下标建树.一开始,每一个节点储存的是从当…
线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来,单次时间复杂度严格\(O(\log n)\). 至于又有合并又有分裂的复杂度,蒟蒻一直不会比较有说服力的证明,直到看见SovietPower巨佬的题解 对于只有合并:合并两棵线段树的过程,是找到它们\(x\)个重合的节点的位置,并将它们合并,而对于不重合的节点会跳过. 注意到合并与分裂类似互逆过程,…
[NOIP2016 DAY1 T2]天天爱跑步 题面: B[NOIP2016 DAY1]天天爱跑步 时间限制 : - MS 空间限制 : 565536 KB 评测说明 : 2s Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一棵包含 \(N\)个结点和\(N-1\) 条边的树, 每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编…
学习线段树合并,以这道题为契机 多谢这篇博客 这里是通过对线段树合并时,顺手统计了对于一颗子树内,是否反转两种情况的逆序对数 这里只对代码进行详细分析,见注解好了 #include<cstdio> #include<algorithm> #define N 210000*30 #define ll long long using namespace std; int n,tmp,ls[N],rs[N],data[N],tot; ll ans,res1,res2; int newtr…
题目大意:给你一棵树,树上一共n个节点,共m次操作,每次操作给一条链上的所有节点分配一个权值,求所有节点被分配到所有的权值里,出现次数最多的权值是多少,如果出现次数相同就输出最小的. (我辣鸡bzoj的权限号,洛谷上P4556也有这道题) 线段树合并入门题 也是比较常规的树上链的点差分 每次操作都在x,y上+1,在lca(x,y),fa[lca(x,y)]上-1 然后对每个点的所有差分操作构建一颗动态开点线段树,然后从叶节点向上合并即可 特别的,只有线段树的最底层存的是实际打的差分,而上层节点仅…
layout: post title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并) author: "luowentaoaa" catalog: true tags: mathjax: true - kuangbin - 字符串 " target="_blank" style="font-size:24px;">传送门 题意 给出一个长度为\(n\)字符串\(s\), \(…
题目大意: 在$n$个带权点上维护两个操作: 1)在点$u,v$间连一条边: 2)询问点$u$所在联通块中权值第$k$小的点的编号,若该联通块中的点的数目小于$k$,则输出$-1$: 传送门 上周的模拟赛在一道线段树合并的题目上gg了,来学习一个. 对每一个联通块,我们维护一棵权值线段树.查询时,若左子树大小大于等于$k$进入左子树,否则进入右子树: 因为每棵线段树同构,所以对于任意两棵线段树可以进行合并操作: int merge(int x,int y){ if(!x)return y; if…
题目链接:XJOI - NOI2015-13 - C 题目分析 使用神奇的线段树合并在 O(nlogn) 的时间复杂度内解决这道题目. 对树上的每个点都建立一棵线段树,key是时间(即第几次操作),动态开点. 线段树的节点维护两个值,一个是这段时间内的 1 操作个数,另一个是这段时间内变化的黑色节点权值和. 在处理所有操作的时候,每棵线段树都是仅代表树上的一个点,因此线段树的每个节点维护的就是这段时间内以这个点为 a 的 1 操作个数和这段时间内这个点的黑色节点权值和(这个点 x 由黑变白就 -…
题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换左右子树无关,是否交换左右子树取决于交换后 “跨越 x 左子树与右子树的逆序对” 是否会减小. 因此我们要求出两种情况下的逆序对数,使用线段树合并,对每个节点建一棵线段树,然后合并的同时就求出两种情况下的逆序对. 代码 #include <iostream> #include <cstdli…
路径(x, y) +z : u处+z, v处+z, lca(u,v)处-z, fa(lca)处-z, 然后dfs一遍, 用线段树合并. O(M log M + M log N). 复杂度看起来不高, 但是跑起来很慢. 另一种做法是先树链剖分, 转成序列上的情况, 然后依旧是差分+线段树维护, O(M log N log M). 但是实际跑起来好像更快... ----------------------------------------------------------------------…
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含…
[bzoj2243][SDOI2011]染色 2017年10月20日 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如"112221"由3段组成:"11"."222"和"1". 请你写一个程序依次完成这m个操作. Input 第一行包含2个整数n和m,分别表示节点数和操作数: 第…
3702: 二叉树 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 600  Solved: 272[Submit][Status][Discuss] Description 现在有一棵二叉树,所有非叶子节点都有两个孩子.在每个叶子节点上有一个权值(有n个叶子节点,满足这些权值为1..n的一个排列).可以任意交换每个非叶子节点的左右孩子.要求进行一系列交换,使得最终所有叶子节点的权值按照中序遍历写出来,逆序对个数最少. Input 第一行n下面每行…
BZOJ_2212_[Poi2011]Tree Rotations_线段树合并 Description Byteasar the gardener is growing a rare tree called Rotatus Informatikus. It has some interesting features: The tree consists of straight branches, bifurcations and leaves. The trunk stemming from t…
B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛.现在有两种操作:B x y表示在岛 x与岛y之间修建一座新桥.Q x k表示询问当前与岛 x连通的所有岛中第k重要的是哪座岛,即所有与岛 x连通的岛中重要度排名第 k小的岛是哪座,请你输出那个岛的编号. 对于100%的数据n≤100000,m≤n…
BZOJ_3307_雨天的尾巴_线段树合并 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后,每个点存放最多的是哪种物品. Input 第一行数字N,M 接下来N-1行,每行两个数字a,b,表示a与b间有一条边 再接下来M行,每行三个数字x,y,z.如题 Output 输出有N行 每i行的数字表示第i个点存放最多的物品是哪一种,如果有 多种物品的数量一样,输出编号最小的.如果某个点没有物品…
题目链接 [洛谷] 题解 很明显是要用线段树合并的. 对于当前的每一个连通块都建立一个权值线段树. 权值线段树处理操作中的\(k\)大的问题. 如果需要合并,那么就线段树暴力合并,时间复杂度是\(nlogn\),均摊下来就是\(logn\). 判断联通性的问题就用并查集来解决. 如果在同一个联通块里,就不能合并,否则会出一点问题. 代码 #include <bits/stdc++.h> using namespace std; const int N = 3000000 + 6; int rt…
求所有可能联通块的第k大值的和,考虑枚举这个值: $ans=\sum\limits_{i=1}^{W}{i\sum\limits_{S}{[i是第K大]}}$ 设cnt[i]为连通块中值>=i的个数 $ans=\sum\limits_{i=1}^{W}{i\sum\limits_{S}{[cnt[i]>=K]-[cnt[i+1]>=K]}}$ $ans=\sum\limits_{i=1}^{W}{\sum\limits_{S}{[cnt[i]>=K]}}$ 于是先考虑树上dp,设f…
洛谷 Codeforces 思路 最初的想法:后缀数组+区间众数,似乎并不能过. 既然后缀数组不行,那就按照套路建出广义SAM,然后把\(S\)放在上面跑,得到以每个点结尾会到SAM上哪个节点. 询问时对于\(p_r\)所在的节点,倍增往parent树上跳,找到包含\([p_l,p_r]\)的最小区间. 然后统计该节点\([l,r]\)的模式串中最多的是谁,用线段树合并实现. 好像就做完了? 特判 一般情况下,如果匹配到\(p_r\),那么\(S(p_l,p_r)\)一定时当前节点的祖先. 但有…
传送门 思路 按照套路,直接上后缀自动机. 部分分:\(l=1,r=|S|\) 首先把\(S\)和\(T\)的后缀自动机都建出来. 考虑枚举\(T\)中的右端点\(r\),查询以\(r\)结尾的串最长可以往左延伸多长,使得它仍然是\(S\)的子串.记该长度为\(lim_r\). \(lim_r\)可以在\(SAM_S\)中瞎跳跳出来. 那么答案即为 \[ \sum_{i=2}^{cnt} \max(0,len_i-\max(len_{fa_i},lim_{pos_i})) \] 其中\(i\)是…
很久以前写过二分答案离线的做法,比较好理解.事实上这还是一个线段树合并+分裂的板子题,相比离线做法以更优的复杂度做了更多的事情.具体不说了.怎么交了一遍luogu上就跑第一了啊 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<set> us…
https://codeforces.com/contest/893/problem/F 题意: 给一个有根树, 多次查询,每次查询对于$x$i点的子树中,距离$x$小于等于$k$的所有点中权值最小的一个 查询强制在线 题解: 显然,暴力就是,对于每次搜索深搜距离x小于$k$的所有点搜索 那么我们考虑优化 首先,查询对$x$距离小于$k$的所有点,等价于在整颗树上,查询$\forall dep(x)≤dep(i)≤dep(x)+k$中,在$x$子树中的点的最小值 那么,一个大胆的想法就是,对于每…