您的位置:首页 > 理论基础 > 数据结构算法

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]。


线段树。线段树练习题集

扫描线

模板

RMQ

int 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)];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: