线段树

wangdy带佬给的权值线段树模板

六眼飞鱼酱① 提交于 2019-12-03 11:10:44
实为1027练习题C-遥色点对题解 给出一张由编号1到n的n个点和m条边构成的无向图。每条边都有一定的长度。 定义,一条路径的“代价”:该路径上最长一条边的长度。 定义,点x到点y的“点距”:点x到点y的最小代价。 图中每个点都被涂上了颜色,第i号点的颜色编号为Ci。 满足x<y 且|Cx-Cy|>=K 的任意一对点(x,y)都被称为“遥色点对” 现在需要你求出图中所有遥色点对的点距之和。 动态开点线段树启发式合并 #include<stdio.h> #include<bits/stdc++.h> #define f(a,b,c) for(register int a=(b);a<=(c);++a) #define ff(a,b,c) for(register int a=(b);a>=(c);--a) #define ll long long #define max(a,b) ((a)>(b)?(a):(b)) //#define int long long char pbuf[1<<20],*pp1=pbuf; inline void push(char c){*pp1=c;pp1=(pp1-pbuf==(1<<20)-1)?(fwrite(pbuf,1,1<<20,stdout),pbuf):(pp1+1);} //#define pc push #define pc

Codeforces 1146E Hot is Cold 线段树

删除回忆录丶 提交于 2019-12-03 10:47:19
Hot is Cold 好像我写麻烦了, 其实只用线段树维护区间每个数反转, 区间赋值就可以。 #include<bits/stdc++.h> using namespace std; const int N = (int)1e5 + 7; int n, q, pos, a[N]; char op[N]; struct Bit { int a[N]; void modify(int x, int v) { for(int i = x; i < N; i += i & -i) { a[i] += v; } } int query(int x) { int ans = 0; for(int i = x; i; i -= i & -i) { ans += a[i]; } return ans; } } bit; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 struct SegmentTree { int a[N << 2], lazy[N << 2], flip[N << 2]; inline void push(int rt) { if(lazy[rt]) { a[rt << 1] = lazy[rt]; a[rt << 1 | 1] = lazy[rt]; lazy[rt << 1] = lazy

P3834 【模板】可持久化线段树 1(主席树)

半城伤御伤魂 提交于 2019-12-03 10:35:35
P3834 【模板】可持久化线段树 1(主席树) 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 2e5+5; 4 int n, q, m, cnt = 0; 5 int a[maxn], b[maxn], T[maxn]; 6 int sum[maxn<<5], L[maxn<<5], R[maxn<<5]; 7 inline int build(int l, int r) { 8 int rt = ++cnt; 9 sum[rt] = 0; 10 if (l < r) { 11 int mid = (l+r)/2; 12 L[rt] = build(l, mid); 13 R[rt] = build(mid+1, r); 14 } 15 return rt; 16 } 17 inline int update(int pre, int l, int r, int x) { 18 int rt = ++cnt; 19 L[rt] = L[pre]; R[rt] = R[pre]; sum[rt] = sum[pre]+1; 20 if (l < r) { 21 int mid = (l+r)/2; 22 if (x <= mid) L[rt] = update(L[pre], l, mid,

ll

♀尐吖头ヾ 提交于 2019-12-03 10:20:19
11.3 放假回来,晚上考的,困。 T1想了个分块的思路,打了1h发现伪了。然后写线段树,写了1h发现也是伪的,最后交暴力了。听了听线段树维护单调栈,发现以前之所以不能理解cal函数,是因为对于维护单调栈有点误解,其实是算贡献,不是真的栈,左儿子只受到传入参量的影响,右儿子要么依旧受到左儿子控制,要么受到传入参量控制,依旧受到控制可以直接用sum[p]-sum[p<<1],取决于pushup的sum[p]=sum[p<<1]+cal(p<<1)。当然可以维护一个额外参量。 T2直接就输出-1了。由于原料没有限制,每天做电脑的最小原料钱是可以直接单变量干出来的。然后用权值线段树开一个仓库,先把所有的电脑认为是在第一天做的存进去,然后取出的时候再加上存电脑的钱,动态的删除已选元素,删除多余的元素,贪心的取最小,删最大。-1随便特判一下。 T3打了30Dfs,然后挂上了一个基于反悔堆的贪心,没有多分。按照A小到大排序,两两分组,选取其中B比较大的,这样B必然满足,A的最坏情况是全都是小的,然而在选择集合不变的基础上,将分组向右平移,则达成两两分组选择的A较大。所以必然有解。 附录 : 随行的数据生成器,插件和飚程。 来源: https://www.cnblogs.com/Yu-shi/p/11790716.html

模拟97 题解

喜欢而已 提交于 2019-12-03 10:19:26
A. 小盆友的游戏 手玩表找规律。 B. 花 弱智$dp$题,用逆元随便处理一下就能处理字符集很大的问题。 C. 表格 利用了扫描线的思想。 首先将横坐标离散化,对纵坐标建线段树。 枚举横坐标,则矩形转化为在横坐标的左边界$insert$,在右边界+1$erase$。 之后问题是不断取出其中还没有被覆盖的元素,并用线段树维护还有哪些元素没有被覆盖。 用$mx$表示区间中标号最大的还没有被覆盖的元素,$mn$表示区间中能看见的最小的元素。 可以通过$mn$和当前$set$中最大的元素,来进行覆盖的操作,维护信息。 来源: https://www.cnblogs.com/skyh/p/11790685.html

主席树

戏子无情 提交于 2019-12-03 10:06:45
主席树是 以前缀和形式基于 权值线段树 建立的可持久化线段树,可持久化指的是它保存了这棵树的所有历史版本. 最简单的办法是:如果你输入了n个数,那么每输入一个数字a[i],就构造一棵保存了从a[1]到a[i]的权值线段树,由于只增加了log n 的节点数,我们增加改变的节点并将没有改变的子树指向该节点,这样需要的空间开销只有n*(4+logn) 我们可以把第j棵树和第(i-1)棵树上的每个点的权值相减,来得到一棵新的权值线段树,而这个新的权值线段树相当于是输入了a[i]到a[j]以后得到的。 模板题 K-th Number 后面将第 k小/大 说成kth 解决什么问题: 给定一段区间,静态求区间kth 想想方法: 暴力:对于每一个询问,排个序,就行了,时间复杂度O(nmlogn) 莫队+树状数组:树状数组可以求给定区间kth kthkth,使用二分+树状数组,具体不展开,但是多个区间的话,需要不断地进行树状数组的add/del操作,那么使用莫队来优化区间端点的移动问题,时间复杂度O((n+m)√n logn) 莫队复杂度*树状数组复杂度 莫队+平衡树:把树状数组的部分替换成二叉查找树,用splay的一部分操作,需要用到kth操作,不用翻转标记什么的,时间复杂度O((n+m)√n logn)跟上面的一样 目前想想,也就这三种方法,各有优劣,暴力时间复杂度不行,但是可以在线

权值线段树

六月ゝ 毕业季﹏ 提交于 2019-12-03 10:02:46
定义: 权值线段树,基于 普通线段树,但是不同。 举个栗子:对于一个给定的数组,普通线段树可以维护某个子数组中数的和,而权值线段树可以维护某个区间内数组元素出现的次数。 在实现上,由于值域范围通常较大,权值线段树会采用离散化或动态开点的策略优化空间。单次操作时间复杂度o(log n ) 权值线段树的节点用来表示一个区间的数出现的次数 例如: 数 1和2 分别出现3次和5次,则节点1记录 3,节点2 记录5, 1和2的父节点记录它们的和8 . 存储结构 : 堆式存储:rt ,l, r, rt<<! , l, m rt<<1|1 ,m+1, r 结点式存储 struct Node { int sum ,l , r :}; 基本作用: 查询第k小或第k大。 查询某个数排名。 查询整干数组的排序。 查询前驱和后继(比某个数小的最大值,比某个数大的最小值) 基本操作: 单点修改 (单个数出现的次数+1) void update(int l,int r,int rt,int pos) // 当前区间范围 l r 节点 rt 位置 pos { if(l==r) t[rt]++; else { int mid=(l+r)/2; if(pos<=mid) add(l,mid,rt*2,pos); else add(mid+1,r,rt*2+1,pos); t[rt]=t[rt*2]+t[rt*2+1

线段树维护动态连续子段HDU1540

大憨熊 提交于 2019-12-03 09:56:18
题意: http://acm.hdu.edu.cn/showproblem.php?pid=1540 #define IOS ios_base::sync_with_stdio(0); cin.tie(0); #include <cstdio>//sprintf islower isupper #include <cstdlib>//malloc exit strcat itoa system("cls") #include <iostream>//pair #include <fstream>//freopen("C:\\Users\\13606\\Desktop\\草稿.txt","r",stdin); #include <bitset> //#include <map> //#include<unordered_map> #include <vector> #include <stack> #include <set> #include <string.h>//strstr substr #include <string> #include <time.h>//srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9; #include <cmath> #include <deque> #include <queue>/

可持久化线段树

痴心易碎 提交于 2019-12-03 09:11:42
特点 老师说,可持久化线段树一个重要的特点就是,它的询问都是单点询问... 先记这....等我做多了题目之后再补充 李超线段树 用于维护若干个一次函数的最值 核心思想就是标记永久化, 线段树每个节点维护在该区间中点取值最大的线段,查询时求一条从上到下的链上log个线段的最值。 ————一位大佬FlashHu 例题 P4097 [HEOI2013]Segment 思路: 一个区间只有在绝对不可能是答案的时候才更新,否则就把原来的/插入的的区间往下递归,插入的/原来的区间就放在当前区间,这样,我们只要把合适的区间往下递归,合适的区间留下,那么对于当前区间,无论是左边还是右边,我们都能求出最优解 #include<cstdio> #include<algorithm> using namespace std; const int MAX = 40000; int n, lastans, cnt; struct line{ double k, b; int id; line() {} line(int x1, int y1, int x2, int y2, int cnt) : id(cnt) { if(x1 == x2) k = 0, b = max(y1, y2); else k = (double)(y2-y1)/(x2-x1), b = (double)y1-k*x1; }

可持久化线段树学习笔记

混江龙づ霸主 提交于 2019-12-03 06:22:26
目录 前言 1 可持久化线段树 1.1 问题引入 1.2 权值线段树 1.3 可持久化线段树 1.4 例题 2 可持久化数组 2.1 问题引入 2.2 问题解决 2.3 参考代码 前言 这篇文章详细地介绍了可持久化线段树、可持久化数组和可持久化并查集,部分图片尺寸过大,建议单击图片放大观看。转载此文章的任何部分均需注明出处。 @ 1 可持久化线段树 1.1 问题引入 您需要写一个数据结构,维护一个数列 \(a[1...N]\) ,支持以下操作: 输入 l r k ( \(l\leq r,k\leq r-l+1\) ),求 \(a[l...r]\) 中第 \(k\) 小的数。 这就是经典的 “静态区间第 k 小” 问题。 可持久化线段树 (Persistent Segment Tree)可以很好地解决这个问题。在学习可持久化线段树时,我们首先要了解权值线段树。 1.2 权值线段树 权值线段树是一种维护值而非下标的线段树,为了方便理解,有时也被称作 “值域线段树”。 设 \(x\) 是一权值线段树上的一个点,它维护的区间是 \([x.l,x.r]\) ,数据是 \(x.d\) ,则它表示的意思是:原数组中,值在区间 \([x.l,x.r]\) 内的数一共有 \(x.d\) 个。 举个例子。有一个数组 \(a[]=\{1,5,3,8\}\) ,则它的权值线段树是