数据结构
哈希表扁豆
此人不懒,但什么都没写
展开
-
【模板】线段树优化建图
Problem三种方案:v to u,v to [l,r],[l,r] to v。求单源最短路。Solution由于存在结点与区间内所有结点间的连边,可以考虑用线段树优化建图。具体来说维护两个线段树,线段树1表示有向边的终止结点,同时父亲连向儿子权为0;线段树2表示有向边的起始结点,同时儿子连向父亲权为0。两线段树的叶子结点间连无向边权为0(线段树1的叶子结点连向线段树2的叶子结点也可),表示同一结点自己和自己是连通的;对于任意有向边,线段树2连向线段树1,如图:Code#inclu原创 2022-04-20 21:10:04 · 990 阅读 · 0 评论 -
D - Tree(树剖+线段树维护区间开根号)
Problem给定一颗大小为n的树和q此操作,op0:将一条树链上所有点的权值开根号;op1:求一条树链上所有点的权值和。Solution显然要用树剖将树映射到区间上,看到区间和时想用线段树维护,场上感觉线段树好像没法通过打标记维护区间开根号。点权是小于等于1e9的,对于一个点来说最多开六次点权就会变为1,如果某个区间的区间和为r-l+1,就不需要对这个区间再进行开根号操作。因此可以维护一个没有pushdown的线段树,暴力修改到底开根号,效率上最差(全部单点开根号开到1)应该是一般线段树的六分之原创 2021-08-22 06:04:48 · 385 阅读 · 0 评论 -
扫描线线段树(板子+一些理解)
功用求平面内矩形的面积并或周长并。一些理解扫描线线段树维护的是当前扫描线穿过的矩形长度。非叶子结点表示该区间内穿过矩形的长度,叶子结点是离散化的点。具体做法:例如要维护平行于x轴的扫描线,首先对矩形的x坐标离散化,每个矩形相当于覆盖了x轴上的一段区间,然后对多有矩形的上下底边进行排序扫描线从下忘上扫,每次扫到某个矩形的底边就更新线段树,然后算出当前底边到下一底边之间矩形覆盖的面积:tree[1]*Δy。如图,线段树维护当前扫描线扫到的矩形在离散化后的x轴上所覆盖的长度,扫描线从最底下的红色原创 2021-08-18 19:49:18 · 348 阅读 · 0 评论 -
A - Circuits(线段树维护区间最大值)
Problem求两条平行线穿过的最大矩形。Solution贪心走不通之后场上想到了枚举,考虑到了定一条之后枚举剩下的,然后剪纸。实际上从剩下的里面找最大就是个区间查询最值问题,线段树可维护。不过还有一些细节要处理:首先区间很长,要对矩形进行离散化;每次确定一条的时候不可能把穿过的所有矩形的对应区间进行修改(这样做可能比暴力还差),实际上这样产生的来回修改毫无意义,顺着这条优化思路,能不能想个办法保证每个矩形只对线段树做两次修改操作(离散化产生两个点)?选择一个矩形下边界的时候将其在区间删掉,在选择原创 2021-08-14 00:53:44 · 342 阅读 · 0 评论 -
P4644 [USACO05DEC]Cleaning Shifts S(线段树维护DP)
将目标区间[m,e]转换为[1,e-m+1],同时转换每个奶牛的工作区间。dp[i]表示覆盖区间[1,i]所需最小代价,dp[T2]=min(dp[i]+s),T1-1<=i<=T2-1。状态转移方程涉及区间查询最小值,因此可以丢进线段树维护。时间复杂度O(ne)降至O(nloge)。初始将cow按T2从小到大排序,segmenttree[0,0]=0。#include <iostream>#include <cstdio>#include <alg.原创 2021-07-28 11:56:05 · 212 阅读 · 0 评论 -
Trie(前缀树)
字面意思,保存字符串前缀的树型结构。根到任意节点的路径代表一个前缀,每个结点一个编号,根的编号为0。Trie如上图,用二维数组ch[][]建树(类似邻接矩阵),ch[u][c]表示结点u通过编号为c的字母所到达的结点(u编号为c的子节点),同时为方便维护每个结点u对应权值val[u],如可以用来区分单词几点与非单词结点。UVA1401 Remember the Word Trie+Dp#include <iostream>#include <cstdio>#inc.原创 2021-06-15 21:36:27 · 146 阅读 · 2 评论 -
单调栈(洛谷模板+例题)
问题引入给定一个序列,求序列中每一个位置的f(i),f(i)为第i个元素右边第一个大于ai的元素的下标;分析从一个元素出发向右看,若出现单调不增部分i~j,显然 i~j不会影响i左边的f值,整个问题的求解与单调性有关。单调栈:字面意思,具有元素单调性的栈;在这个题中我们维护一个自栈顶至栈底对于第i个元素,...原创 2020-12-31 12:03:47 · 904 阅读 · 0 评论 -
可持久化线段树(主席树)
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;int n,m,root[200005],a[200005],len,b[200005],tot,li,ri,ki,ans;struct segmenttree{ int lc,rc; int cnt;}tree[4000005];int build(int l,int r){ int p=++tot;原创 2020-11-03 20:13:37 · 88 阅读 · 0 评论 -
线段树
#include<iostream>using namespace std;long long a[100002],tree[400009],ans,tag[400009];void pushup(int x){ tree[x]=tree[x<<1]+tree[x<<1|1];}void build(int x,int l,int r){ if(l==r){ tree[x]=a[l]; return; } int mid=(l+r)>.原创 2020-11-03 20:18:03 · 95 阅读 · 0 评论 -
文艺平衡树
#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int maxn=300009;int ch[maxn][2],fa[maxn],m,rev[maxn]={0},n,a[maxn],rt,size[maxn];void up(int x){ size[x]=size[ch[x][0]]+size[ch[x.原创 2020-11-03 20:23:30 · 105 阅读 · 0 评论 -
树状数组
#include<iostream>using namespace std;int a[500001],b[500001],xx[500001],y[500001],c[500001],m,n,k[500001],kk[500001];int lowbit(int x){ return x&-x;}void adds(int x){ int i=x; while(i<=n) { b[i]+=a[x]; i原创 2020-11-03 20:28:35 · 71 阅读 · 0 评论 -
并查集模板
初始化:每个元素自成一集合,自己为代表元素int a[10086];//a[i]表示i元素所在集合的代表元素 for(int i=1;i<=10086;i++)a[i]=i; 查询(路径压缩)int find(int x){//查询x元素所在集合的代表元素 return a[x]==x?x:a[x]=find(a[x]); }合并void merge(int x,int y){ int xx=find(x),yy=find(y); a[xx]=yy;}.原创 2020-08-06 16:13:30 · 105 阅读 · 0 评论