线段树

洛谷P4556 雨天的尾巴(线段树合并)

自作多情 提交于 2020-02-16 09:54:17
洛谷P4556 雨天的尾巴 题目链接 题解: 因为一个点可能存放多种物品,直接开二维数组进行统计时间、空间复杂度都不能承受。因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一颗权值线段树来维护多种物品以及其数量,然后最后在回溯时合并,这样就可以得到我们所需要的信息了。 因为题目中要求的是哪一种物品,所以我们可以顺带维护一下位置信息,就不用到时候每次去query了。 注意一下,就是当一个点的sum为0时,其pos应该为置为0。 详见代码吧: #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5 + 5; int n, m; struct Edge{ int v, next; }e[N << 1]; int head[N], tot, D; void adde(int u, int v) { e[tot].v = v; e[tot].next = head[u]; head[u] = tot++; } int f[N][22], deep[N] ; int rt[N], ls[N * 100], rs[N * 100], pos[N * 100], sum[N * 100] ; int X[N], Y[N], Z[N], b[N], ans[N

#树状数组,线段树,离散#JZOJ 3854 分组 From 2020.01.16【NOIP提高组】模拟A 组

廉价感情. 提交于 2020-02-15 19:16:53
题目 Bsny所在的精灵社区有 \(n\) 个居民,每个居民有一定的地位和年龄, \(r_i\) 表示第 \(i\) 个人的地位, \(a_i\) 表示第 \(i\) 个人的年龄。 最近社区里要举行活动,要求几个人分成一个小组,小组中必须要有一个队长,要成为队长有这样的条件: 1、队长在小组中的地位应该是最高的(可以并列第一); 2、小组中其他成员的年龄和队长的年龄差距不能超过 \(K\) 。 有些人想和自己亲密的人组在同一个小组,同时希望所在的小组人越多越好。比如 \(x\) 和 \(y\) 想在同一个小组,同时希望它们所在的小组人越多越好,当然,它们也必须选一个符合上述要求的队长,那么问你,要同时包含 \(x\) 和 \(y\) 的小组,最多可以组多少人? 第一行两个整数 \(n\) 和 \(K\) ; 接下来一行输入 \(n\) 个整数: \(r_1, r_2,\dots, r_n\) 接下来一行输入 \(n\) 个整数: \(a_1, a_2,\dots, a_n\) 接下来输入 \(Q\) 表示有 \(Q\) 个询问; 接下来 \(Q\) 行每行输入 \(x, y\) ,表示询问:当 \(x\) 和 \(y\) 组在同一个小组,它们小组最多可以有多少人( \(x\) 和 \(y\) 也有可能被选为队长,只要它们符合条件)。 对于每个询问,输出相应的答案,每个答案占一行。

敌兵布阵 (树状数组&线段树入门)

我只是一个虾纸丫 提交于 2020-02-15 16:54:34
C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。 中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下,Tidy只好打电话向计算机专家Windbreaker求救,Windbreaker说:“死肥仔,叫你平时做多点acm题和看多点算法书,现在尝到苦果了吧!”Tidy说:"我知错了。。。"但Windbreaker已经挂掉电话了。Tidy很苦恼,这么算他真的会崩溃的,聪明的读者,你能写个程序帮他完成这项工作吗

HDU 1166 敌兵布阵(线段树,树状数组)

橙三吉。 提交于 2020-02-15 16:10:03
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 18473 Accepted Submission(s): 8034 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。 中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下

万丈崖壁

假如想象 提交于 2020-02-15 07:47:14
万丈崖壁: 1.写算法博客 写左偏树 写莫队 讲解STL 写主席树(附带树套树) 写可持久化trie树 写zkw线段树 写splay 写AVL 写线段树合并+分裂 写SA后缀数组 写SAM后缀自动机 写最小割树 写Dijkstra(堆优化) 写SPFA 写Floyd 写Tarjan缩点割点双联 写欧拉回路 写差分约束 写2-sat 写Dinic 写匈牙利算法 写两种最小生成树算法 写EK 写HLPP 写Stein 写欧几里得扩展 写卡特兰数 写乘法逆元 写矩阵快速幂 写扩展卢卡斯 写余数求和 写高斯消元 写康托展开 写BSGS北上广深 写凸包 写dp 写马拉车 写二分 写A* 2.学习的算法 EXKMP LCT Treap fhqTreap 替罪羊树 红黑树 分块 cdq分治 数列剖分 块状链表 莫比乌斯反演 FFT 数位dp 博弈论 来源: CSDN 作者: KonnyWen 链接: https://blog.csdn.net/KonnyWen/article/details/104318122

Permutation Separation(线段树)

蹲街弑〆低调 提交于 2020-02-12 23:17:52
题目链接: http://codeforces.com/contest/1295/problem/E 题意:给定一个排列,以及每个位置的价值a[]。现在把当前排列分成前后两部分,可以将左边集合的数扔到右边集合,但需要消费该数对应的代价;同理可以将右边集合的数扔到左边集合,但需要消费该数对应的代价。通过若干次移动操作,实现左边集合数恒小于右边集合数。求最小花费。 题解:最终实现左边集合数恒小于右边集合数,等价于左边数 < v a l <val < v a l ,右边数 > = v a l >=val > = v a l ,对于当前选定的 v a l val v a l ,我们判断每个划分位置 p o s pos p o s ,我们将 < = p o s <=pos < = p o s 的数放在左集合,将 > p o s >pos > p o s 的数放在右集合。那么对于 > p o s , < v a l >pos,<val > p o s , < v a l 的数需要从右集合扔到左集合;对于 < = p o s , > = v a l <=pos,>=val < = p o s , > = v a l 的数需要从左集合扔到右集合。 用数组 m n [ ] mn[] m n [ ] 来表示对于当前 v a l val v a l ,下标划定为 p o s pos p o s

线段树的基本运算

不问归期 提交于 2020-02-12 11:43:10
#include<cstdio> #include<cstring> const int maxn=100010; #define lowbit(i) ((i)&(i)) int c[maxn]; void update(int x,int v) { for(int i=x;i<maxn;i+=lowbit(i)) { c[i]+=v; } } int getsum(int x) { int sum=0; for(int i=x;i>=;i-=lowbit(i)) { sum+=c[i]; } return sum; } 来源: https://www.cnblogs.com/superPG/p/12298097.html

线段树分治总结

纵然是瞬间 提交于 2020-02-12 04:38:47
毕竟学了1天…纪念一下吧 首先一定要对“时间”很清晰,这里的"时间"可能并不是实际的时间,输入中一个删除操作可能不是真的删除,可以理解为操作持续时间而避免删除 和 C D Q CDQ C D Q 分治的区别在于 C D Q CDQ C D Q 经典问题是偏序问题,问题信息一般是计数类或者有可减性,而线段树分治处理其他类型的 询问的类型有两种,一种是带参数询问,即给你个 x x x 问对它进行某些操作后取得最值,还有一种是跟图/并查集相关的(可能因为我做过的题比较少),前者一般根据操作特点能做到均摊 O ( n ) O(n) O ( n ) 或者单次 O ( l o g n ) O(logn) O ( l o g n ) ,后者一般倾向于集中处理(因为查询和查询之间没什么区别) 查询和修改而言,我做过的有单点查询区间修改,单点修改区间查询两种类型,前者将修改分成 l o g n logn l o g n 段后插入在这几段,然后单点询问时候计算经过节点对询问影响,后者考虑修改标记永久化,只管询问的 l o g n logn l o g n 个节点即可 总的而言,线段树分治本身属于套路类的内容,所以本身并不怎么有技巧性 来源: CSDN 作者: Liang-梁 链接: https://blog.csdn.net/qq_37555704/article/details/104270035

Bipartite Checking[CF813F][线段树分治][带权并查集]

时间秒杀一切 提交于 2020-02-12 02:20:48
文章目录 题目 思路 代码 题目 Luogu 2 ≤ n , q ≤ 1 0 5 2\le n,q\le 10^5 2 ≤ n , q ≤ 1 0 5 思路 通过带权并查集判断二分图真是妙(以前没见过) 首先我们能找到每条边的出现时间 [ l i , r i ] [l_i,r_i] [ l i ​ , r i ​ ] ,那么线段树分治后 发现是一个区间修改,单点查询的样子,修改标记永久化即可 然后就只剩下如何处理加边和删边的问题了 然后发现好像网上都把判断二分图当作众所周知… 我们使用带权并查集来解决这个问题,具体而言定义 f a [ u ] = u fa[u]=u f a [ u ] = u 的节点颜色为 0 0 0 ,然后每个点上有一个标记 c u c_u c u ​ 表示和 f a [ u ] fa[u] f a [ u ] 的颜色异同关系,显然一个点的颜色就是它到根的 c u c_u c u ​ 异或和 可以用线段树懒标记类比 一次 ( u , v ) (u,v) ( u , v ) 的加边操作如何实现? 如果 ( u , v ) (u,v) ( u , v ) 不连通,我们首先得到 u , v u,v u , v 各自颜色,如果不同那么并查集合并表示连通性,颜色相同将其中一个并查集顶端颜色变换连接即可 如果 ( u , v ) (u,v) ( u , v ) 连通

线段树学习笔记

给你一囗甜甜゛ 提交于 2020-02-11 23:41:00
当要处理一个数组arr,求一定长度的和,并且对数组的单个值的大小进行修改。不进行特殊处理的话,不妨假设一定长度为n,那么求和的时间复杂度为O(n),修改为O(1)。 如果使用另外一个数组s,为arr的前缀和数组,那么求和的时间复杂度变为O(1),但是修改的时间复杂度变为O(n)。 这样的处理显然并不是很理想。 但使用线段树组进行处理的话,能让求和和修改的时间复杂度变为O(nlogn),从而达到减少时间复杂度的目的。 1.建立一个树状数组。 void build_tree(int arr[],int tree[],int node,int start,int endd) { if(start==endd) tree[node]=arr[endd];//递归的出口 else { int mid=(start+endd)/2; int left_node=2*node+1; int right_node=2*node+2; build_tree(arr,tree,left_node,start,mid); build_tree(arr,tree,right_node,mid+1,endd); tree[node]=tree[left_node]+tree[right_node]; } } 思路其实就是父亲等于左儿子+右儿子。 一直递归下去,直到出口。 2.对数组的区间值的询问 int