2016暑期集训4——数据结构(知识点,模板,简单题题解)
2016-08-06 15:28
357 查看
2016暑期集训4——数据结构(知识点,模板,简单题题解)
知识点
位运算 按位与& 或| 异或^ 取反~ >>右移 相当于除以2 <<左移 相当于乘以2 优先级低 注意运算顺序RMQ问题
线段树O(logn),可以修改,不需要预处理。
ST表需要预处理,O(n)预处理,O(1)查询。
ST表是dp思想,用dp[i][j]表示从i开始2^j个连续点的最值,dp[i][j] = max(dp[i][j-1],dp[i+1<<(j-1)][j-1])。把区间下分为两段,求各自最值。
查询时,如果区间不是2的整幂次,比如查询2~7,长度为6,log6=2,返回max([2~5],[4~7]),中间有重的不影响。
dfs序。大概就是对一棵树dfs,一个节点进去时打个标记,递归子树,出去时打个标记。特点就是一个子树的dfs序(那个标记)是连续的。下面代码。
LCA问题,最近公共祖先。
搜索算法。记录节点深度,比如要找节点uv的祖先,先让u或v往上走,到deep[u]=deep[v],在一起往上走直到走到一起。还有预处理后再进行多次查询nlogn的算法,白书329页。
基于RMQ的算法。首先从跟dfs后得到顶点序列vs[i]和对应深度depth[i],对于每个节点,记其在vs中首次出现的下标id[v]。LCA(u,v)=vs[id[u]<=i<=id[v]中令depth最小的i]。
线段树。线段树练习题集
扫描线
模板
RMQint st[MAXN][20];//st表,表示从i开始2^j个连续点的最值 int mm[MAXN];//对数表 void ST(int n) { memset(st,0,sizeof(st)); memset(mm,0,sizeof(mm)); mm[0]=-1; for(int i=0;i<=n;i++) { if(i>=1) { mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; //求对数表 } st[i][0]=b[i]; } for(int j=1;j<=mm ;j++) { for(int i=0;i+(1<<j)-1<n;i++) { int k=i+(1<<(j-1)); st[i][j]=max(st[i][j-1],st[k][j-1]); } } } int rmq(int l,int r) { int k=mm[r-l+1]; return (max(st[l][k],st[r-(1<<k)+1][k])); }
DFS序
//dfs标号记得调试看结果再决定怎么用 typedef struct{ int in,out; } Dfs; Dfs dffs[MAXN]; bool visit[MAXN]; void dfs(int n) { if(!visit ) { dffs .in=cnt++; visit =true; } else { return; } for(int i=head ;~i;i=G[i].next)//注意这个是链式前向星建图的 { dfs(G[i].to); } if(visit ) { dffs .out=(cnt-1); } }
LCA问题 单次的搜索算法
vector<int>G[MAXN];//图的邻接表 int root;//根结点编号 int parent[MAXN];//父节点编号 跟的父节点是-1 int depth[MAXN];//节点深度 void dfs(int v,int p,int d) { parent[v]=p; depth[v]=d; for(int i=0;i<G[v].size();i++) { if(G[v][i]!=p) { dfs(G[v][i],v,d+1); } } } void init() { dfs(root,-1,0); } //计算LCA int lca(int u,int v) { //让uv高度相同 while(depth[u]>depth[v]) u=parent[u]; while(depth[v]>depth[u]) v=parent[v]; while(u!=v) { u=parent[u]; v=parent[v]; } return u; }
LCA问题 基于RMQ的算法
vector<int>G[MAXN];//图的邻接表 int root;//根结点编号 int vs[MAXN*2+1];//DFS访问顺序 int depth[MAXN*2+1];//节点深度 int id[MAXN];//各顶点在vs中首次出现的下标 void dfs(int v,int p,int d,int &k) { id[v]=k; vs[k]=v; depth[k++]=d; for(int i=0;i<G[v].size();i++) { if(G[v][i]!=p) { dfs(G[v][i],v,d+1,k); vs[k]=v; depth[k++]=d; } } } void init() { int k=0; dfs(root,-1,0,k); //初始化RMQ ??? } //计算LCA int lca(int u,int v) { return vs[rmq(min(id[u],id[v]),max(id[u],id[v])+1)]; }
相关文章推荐
- 2016暑期集训2——数论(知识点,模板,简单题题解)
- 2016暑期集训---搜索(简单BFS)
- 2016暑期集训---搜索(简单BFS)
- 2016暑期集训---搜索(简单BFS+路径储存)
- 2016暑期集训13 B瞬间移动 HDU 5698
- 暑期集训day3训练(数据结构)
- 2016暑期集训16A强迫症
- NOIP复赛知识点复习:算法/数据结构模板
- 2016-2017 HPU暑期集训练习赛
- 2010暑期集训第一专题(数据结构)总结
- 2016暑期集训12C L国货物运输 HDU 5699 货物运输
- 2016暑期集训14B 奶牛逃跑 cowrun
- 2016暑期集训10 C吴传之火烧连营
- OpenJudge 百练 2016 ACM 暑期课练习题 简单的整数划分问题
- 2016暑期集训集中贴
- 2016暑期集训---周赛(水题)
- 2016暑期集训10 A魏传之长坂逆袭
- 2016暑期集训1B 构造回文字符串
- 2016暑期集训1A 组合数
- 2016暑期集训16C星座