一、赢者树。
为决定一场比赛的赢家,假设每个选手有一得分且赢者取决于对两选手得分的比较。在最小赢者树(min winner tree)中,得分小的选手获胜;同理,在最大赢者树(max winner tree)中,得分大的选手获胜。有时,也可用左孩子对应的选手代表赢家节点。
图 10-2a 给出含8名选手的最小赢者树,而图10-2b 给出含5名选手的最大赢者树。每个外部节点之下的数字表示选手得分。
定义 [赢者树] 对于n 名选手,赢者树是一棵含n 个叶子节点,n-1个非叶子节点的完全二叉树,其中每个内部节点记录了相应赛局的赢家。
操作一:初始化一颗赢者树。
template
void wtree_init(t *wt,t *a,int n)
int i;
for(i=0;i for(i=n-1;i>0;i--)wt[i]=min(a[i*2],a[i*2+1]);
操作二:修改一个叶结点的值。
template
void wtree_update(t *wt,t v,int s)
s/=2;while(max(wt[s*2],wt[s*2+1])!wt[s]&&s>1)
操作三:求解子区间的“赢者”
template
t wtree_cal(t *wt,int fr,int re)
int res=inf;
while(fr
return res;
template
t wtree_cal_rec(t *wt,int fr,int re)
if(fr==re) return wt[fr];
if(fr%2==1) return min(wt[fr],wtree_cal_rec(wt,fr+1,re));
if(re%2==1) return min(wt[re],wtree_cal_rec(wt,fr,re-1));
return min(wtree_cal_rec(fr/2,re/2));
例1-1 [排序] 可用一个最小赢者树在 (nl o gn)时间内对n 个元素进行排序。
首先,用n 个元素代表n 名选手对赢者树进行初始化。利用元素的值来决定每场比赛的结果,最后的赢家为具有最小值的元素,然后将该选手(元素)的值改为最大值 (如∞),使它赢不了其他任何选手。
在此基础上,重构该赢者树,所得到的最终赢家为该排序序列中的下一个元素。以此类推,可以完成n 个元素的排序,时耗为 (n)。每次改变竞赛赢家的值并重构赢者树的时耗为 ( l o gn),这个过程共需执行n- 1次,因此整个排序过程所需要的时间为 (nl o gn)。
例1-2 [rmq问题] 给定长度不超过100000的整数序列,对这个序列进行不超过100000次操作,操作有两种类型:,将第i个元素的值改成v;,询问区间[i,j]上的最大值。
要求回答所有询问。
例1-3 将上例中的第二种操作改为询问区间[i,j]上的和值。
例1-4 给一张平面星图,计算每颗星星左下方的星星总数。
一棵含有n个叶结点的赢者树t[n]对应于一个含有n个元素的序列a[n],它的节点上存储了a[n]的子序列的统计信息。他使得对a[n]的单点更新和任意子区间的统计均可以再logn时间内完成。
二、线段树。
定义 [线段树] 一棵二叉树,记为t (a,b),参数a,b表示该节点表示区间[a,b]。区间的长度b-a记为l。递归定义t[a,b]:
若l>1 :[a, (a+b)/2]为 t的左儿子 ,a+b)/2,b]为t的右儿子。
若l=1 :t为一个叶子节点。
表示区间[1, 10]的线段树表示如下:
定理:线段树把区间上的任意一条线段都分成不超过 2logl条线段。
这个结论为线段树能在 o(logl)的时间内完成一条线段的插入、删除、计算等工作,提供了理论依据。
struct stnode
int fr,re;
统计与操作信息。
线段树与赢者树一样对应于一个序列,相比于赢者树它支持对序列子区间实施整体变更。它主要有以下三种操作:
操作一:创建一棵线段树。
void build(stnode *a,int fr,int re,int s)
a[s].fr=fr;
a[s].re=re;
if(re-fr>1)
操作二:更新一个子区间。
void insert( *a,int fr,int re,int s,//
int mid;
if(fr==a[s].fr&&re==a[s].re)
mid=(a[s].fr+a[s].re)/2;
if(fr
else if(re<=mid) insert(a,fr,re,s*2,v);
else insert(a,fr,re,s*2+1,v);
操作三:求解一个子区间。
例2-1 给定长度不超过100000的整数序列,对这个序列进行不超过100000次操作,操作有两种类型:,将区间[i,j]上的每个元素的值增加v;,询问区间[i,j]上的最大值。
要求回答所有询问。
template
struct stnode
int fr,re;
int v;
tstat st;
template
void build(stnode *a,int fr,int re,int s)
a[s].fr=fr;
a[s].re=re;
a[s].v=0;
(a[s].st).init(fr,re);
if(re-fr>1)
template
void insert(stnode *a,int fr,int re,int s,int v)
int mid;
if(fr==a[s].fr&&re==a[s].re)
return;
mid=(a[s].fr+a[s].re)/2;
if(fr
else if(re<=mid) insert(a,fr,re,s*2,v);
else insert(a,fr,re,s*2+1,v);
(a[s].st).unite(a[s*2].st,a[s*2+1].st);
(a[s].st).update(a[s].v);
template
tstat calculate(stnode *a,int fr,int re,int s)
int mid;
tstat tmp;
if(fr==a[s].fr&&re==a[s].re) return a[s].st;
mid=(a[s].fr+a[s].re)/2;
if(fr else if(re<=mid) tmp=calculate(a,fr,re,s*2);
else tmp=calculate(a,fr,re,s*2+1);
return tmp;
class stat
public:
bool m;
void init(int fr,int re)
bool update(int v)
void unite(stat a,stat b)
例2-2 球矩形并的面积和体积。
class stat
public:
int s,l;
void init(int fr,int re)
bool update(int v)
return false;
void unite(stat a,stat b)
class stat
public:
bool bfr,bre;
int n;
void init(int fr,int re)
bool update(int v)
return false;
void unite(stat a,stat b)
bfr=bre=
3概率与统计问题作业
高考中概率与统计问题的热点题型。1.2016 全国 卷 某险种的基本保费为a 单位 元 继续购买该险种的投保人称为续保人,续保人本年度的保费与其上年度出险次数的关联如下 设该险种一续保人一年内出险次数与相应概率如下 1 求一续保人本年度的保费高于基本保费的概率 2 若一续保人本年度的保费高于基本保费...
高级统计实务与案例分析大纲
高级统计实务与案例分析 考试大纲。一 考试目的。遵循突出能力考核的原则,以统计工作流程为主线,全面考察统计专业技术人员运用数据信息,分析 判断 处理统计业务和解决统计工作实际问题的综合能力。二 考试基本要求。一 统计调查设计。1.准确把握 企事业单位和社会公众等统计用户需求,熟悉国家统计指标体系和分...
高级统计实务与案例分析试卷 2019
二 一六年高级统计师资格考评结合考试。1 本试卷有两部分,共8道题,满分150分。其中第一部分为必答题,共6道题,满分130分 第二部分为选答题,要求选答1道题,若多答,评卷时只对前1道答题打分,满分20分。2 在你拿到试卷的同时将得到一份专用答题卡,所有试题务必在专用答题卡上作答,在试卷或草稿纸上...