目录

  • 线段树

    • 例题

      • 题面
    • 练习
      • 1
      • 2
      • 3
      • 4
      • 5
    • 小解区间操作
  • 二叉堆
    • 例题
    • 思路

@

线段树

例题

题面

时间限制: 1 Sec  内存限制: 128 MB
【题意】给出N个数,两种操作:1、C x y:修改第x个数的值为y;2、P x y:求第x到第y个的最大值,注:x未必比y小【输入格式】第一行输入N和M(0<N<=200000,0<M<5000),N表示有N个数,M表示有M个操作;下来N个数ai(  0<=|ai|<=10^6 );然后是M个操作。【输出格式】遇到P操作的时候,输出结果。【样例输入】
5 61 2 3 4 5P 1 5C 3 6P 3 4P 4 5C 2 9P 1 5
【样例输出】
5659

### 思路
我们都知道,江湖上有个算法叫线段树。

他是怎么搞的呢?

首先我们看向这么一个序列:\(1,2,3,4,5\)

我们申请一个根节点管理的是\(1,2,3,4,5\)。

但是这么多点是不是有点麻烦?

于是,根节点又申请了左右儿子,左儿子管理的是\(1,2,3\),右儿子是\(4,5\)。

也就是\(l=1,r=5,mid=(l+r)/2=3\),然后左儿子管理的是\(l,mid\),右儿子管理的是\(mid+1,r\)。

然后左右儿子又去申请左右儿子,直到他管理的是一个人。

然后每个点都要维护区间的信息。

查询修改跳儿子就行了。

#include<bits/stdc++.h>
using  namespace  std;
int  a[210000];
struct  node
{int  l,r,lc,rc,c;
}tr[410000];int  len,n,m;
void  bt(int  l,int  r)
{len++;int  now=len;tr[now].l=l;tr[now].r=r;if(l==r)tr[now].c=a[l];else{int mid=(l+r)/2;tr[now].lc=len+1;bt(l,mid);tr[now].rc=len+1;bt(mid+1,r);tr[now].c=max(tr[tr[now].lc].c,tr[tr[now].rc].c);}
}
void  change(int  now,int  x,int  k)
{if(tr[now].l==tr[now].r){tr[now].c=k;return  ;}int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(x<=mid)change(lc,x,k);else  change(rc,x,k);tr[now].c=max(tr[lc].c,tr[rc].c);//在每次change完别忘记维护自己的信息
}
int  findans(int  now,int  l,int  r)
{if(tr[now].l==l  &&  tr[now].r==r)return  tr[now].c;int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(r<=mid)return  findans(lc,l,r);else  if(mid+1<=l)return  findans(rc,l,r);else  return  max(findans(lc,l,mid),findans(rc,mid+1,r));
}
int  main()
{scanf("%d%d",&n,&m);for(int  i=1;i<=n;i++)scanf("%d",&a[i]);bt(1,n);for(int  i=1;i<=m;i++){char  ss[10];int  x,y;scanf("%s%d%d",ss,&x,&y);if(ss[0]=='C')change(1,x,y);else{if(x>y)swap(x,y);printf("%d\n",findans(1,x,y));}}return  0;
}

很容易看出时间复杂度为\(O(nlogn)\)。

练习

1

时间限制: 1 Sec  内存限制: 128 MB
【题意】有L段线段(编号为1~L, (0 <= L <= 1000000)),一开始全部线段是颜色1。有两种操作:
1、C A B tt :把第A至第B个线段染成第tt种颜色
2、P A B :询问第A至第B个线段有多少种不一样的颜色。注意:
1、A有可能比B大。
2、颜色的编号<=50;
数据较水,不用担心特殊的情况,按照题解打也能AC,数据强的版本已放在1238
【输入格式】第一行含有两个整数 L and M (1 <= M <= 100000).  M代表操作次数. 下来M行操作【输出格式】有询问的时候输出【样例输入】
2 4C 1 1 2P 1 2C 2 2 2P 1 2
【样例输出】
21

这题我们的\(c\)表示的是如果有多种颜色的话为\(-1\),否则就为这个唯一的颜色的编号。
查询是暴力区间查。
但是正解应该是每个节点多套个bitset(STL里面的好东西),外面也用个bitset记录答案,然后办到\(O(nlogn)\)。

这种非正解做法理论复杂度\(O(n^2)\),但数据水呀。

#include<cstdio>
#include<cstring>
#include<algorithm>
using  namespace  std;
struct  node
{int  l,r,lc,rc,c;
}tr[2100000];int  len,n,m;
bool  v[2100];
void  bt(int  l,int  r)
{len++;int  now=len;tr[now].l=l;tr[now].r=r;tr[now].c=1;if(l<r){int  mid=(l+r)/2;tr[now].lc=len+1;bt(l,mid);tr[now].rc=len+1;bt(mid+1,r);}
}
int  findans(int  now,int  l,int  r)
{if(tr[now].c!=-1){if(v[tr[now].c]==true){v[tr[now].c]=false;return  1;}else  return  0;}int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(r<=mid)return  findans(lc,l,r);else  if(mid+1<=l)return  findans(rc,l,r);else  return  findans(lc,l,mid)+findans(rc,mid+1,r);
}
void  change(int  now,int  l,int  r,int  c)
{if(tr[now].c==c)return  ;if(tr[now].l==l  &&  tr[now].r==r){tr[now].c=c;return  ;}int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(tr[now].c!=-1)tr[lc].c=tr[rc].c=tr[now].c;if(r<=mid)change(lc,l,r,c);else  if(mid+1<=l)change(rc,l,r,c);else  change(lc,l,mid,c),change(rc,mid+1,r,c);if(tr[lc].c!=tr[rc].c)tr[now].c=-1;else  tr[now].c=tr[lc].c;//维护本身的信息
}
int  main()
{scanf("%d%d",&n,&m);bt(1,n);for(int  i=1;i<=m;i++){char  ss[10];int  x,y,c;scanf("%s%d%d",ss,&x,&y);if(x>y)swap(x,y);if(ss[0]=='P'){memset(v,true,sizeof(v));printf("%d\n",findans(1,x,y));}else{scanf("%d",&c);change(1,x,y,c);}}return  0;
}

2

时间限制: 1 Sec  内存限制: 128 MB
【题意】有L段线段(编号为1~L, (1 <= L <= 1 0000 0000   没错,就是1亿 )) ,一开始全部线段是颜色1。有两种操作:
1、C A B tt :把第A至第B个线段染成第tt种颜色
2、P A B :询问第A至第B个线段有多少种不一样的颜色。注意:
1、A有可能比B大。
2、颜色的编号<=50;
【输入格式】第一行含有两个整数 L and M (1 <= M <= 100000).  M代表操作次数. 下来M行操作【输出格式】有询问的时候输出【样例输入1】
2 4C 1 1 2P 1 2C 2 2 2P 1 2
【样例输出1】
21
【样例输入2】
10 3C 1 2 2C 4 10 3P 1 10
【样例输出2】
3 

不就是个离散化吗,离散化什么,就是把每个编号从小到大排一遍,然后把他的值改成排名,然后再操作的时候一直用排名操作,使得省了一坨空间。

但是这题有点不一样,如果你的线段树的每个点维护的是区间内点情况,那么每个排名之间要留个位置,为什么?因为有可能你把编号\(1,2,4,5\)改成了\(1,2,3,4\),导致查询的时候原本的\(3\)查不到,当然还有另外一种办法,线段树维护的是一个区间,然后右儿子维护的是\(mid,r\),然后直到\(l+1==r\)的话就不申请节点了,这样子的话也可以改成\(1,2,3,4\),也是比较推介的做法。

这里用的是第一种方法:

#include<bits/stdc++.h>
using  namespace  std;
struct  LSnode
{int  x,y,z;
}A[510000],B[510000];
struct  node
{int  l,r,lc,rc,c;
}tr[510000];int  len,n,m,kk[110000],tt;
char  st[110000][5];
bool  cmp(LSnode  x,LSnode  y){return  x.x<y.x;}
void  bt(int  l,int  r)
{len++;int  now=len;tr[now].l=l;tr[now].r=r;tr[now].c=1;if(l<r){int  mid=(l+r)/2;tr[now].lc=len+1;bt(l,mid);tr[now].rc=len+1;bt(mid+1,r);}
}
bool  v[2100];
int  find(int  now,int  l,int  r)
{if(tr[now].c>0){if(v[tr[now].c]==true){v[tr[now].c]=false;return  1;}else  return  0;}int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(r<=mid)return  find(lc,l,r);else  if(mid+1<=l)return  find(rc,l,r);else  return  find(lc,l,mid)+find(rc,mid+1,r);
}
void  change(int  now,int  l,int  r,int  k)
{if(tr[now].c==k)return  ;if(tr[now].l==l  &&  tr[now].r==r){tr[now].c=k;return  ;}int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(tr[now].c>0)tr[lc].c=tr[rc].c=tr[now].c;if(r<=mid)change(lc,l,r,k);else  if(mid+1<=l)change(rc,l,r,k);else  change(lc,l,mid,k),change(rc,mid+1,r,k);if(tr[lc].c==tr[rc].c)tr[now].c=tr[lc].c;else  tr[now].c=-1;
}
int  main()
{scanf("%d%d",&n,&m);for(int  i=1;i<=m;i++){scanf("%s",st[i]);if(st[i][0]=='C')scanf("%d%d%d",&A[i*2-1].x,&A[i*2].x,&kk[i]);else  scanf("%d%d",&A[i*2-1].x,&A[i*2].x);if(A[i*2-1].x>A[i*2].x)swap(A[i*2-1].x,A[i*2].x);A[i*2-1].z=i*2-1;A[i*2].z=i*2;B[i*2-1]=A[i*2-1];B[i*2]=A[i*2];}sort(B+1,B+m*2+1,cmp);B[0].x=999999999;for(int  i=1;i<=m*2;i++){if(B[i].x!=B[i-1].x){if(B[i].x==B[i-1].x+1)tt++;//如果两个数字不是贴在一起的话,就直接+2else  tt+=2;}A[B[i].z].y=tt;}bt(1,tt);for(int  i=1;i<=m;i++){if(st[i][0]=='C')change(1,A[i*2-1].y,A[i*2].y,kk[i]);else{memset(v,true,sizeof(v));printf("%d\n",find(1,A[i*2-1].y,A[i*2].y));}} return  0;
}

3

【题意】有n(1~100000)个连续的格子,编号为1……n,每个格子的颜色有3种(分别是1、2、3)。有m(1~100000)操作,操作有2种:1 x y k:表示第x个格子至第y个格子全染色为k(1<=k<=3)2 x y:表示询问第x个格子至第y个格子有多少条线段(相邻两个格子的颜色相同则同属一条线段)。【输入格式】第一行n和m。第二行n个数,分别表格n个格子的颜色。下来m行,每行表示一个操作。【输出格式】遇到操作2,则输出答案【样例输入】
5 52 1 1 2 12 1 51 4 4 12 1 51 1 1 12 1 5
【样例输出】
421 

第2个需要设个全局变量。
然后就没什么了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using  namespace  std;
struct  node
{int  l,r,lc,rc,c;
}tr[210000];int  len,n,m,a[110000],cc/*多设一个全局变量*/;
void  bt(int  l,int  r)
{len++;int  now=len;tr[now].l=l;tr[now].r=r;if(l==r)tr[now].c=a[l];else{int  mid=(l+r)/2;tr[now].lc=len+1;bt(l,mid);tr[now].rc=len+1;bt(mid+1,r);if(tr[tr[now].lc].c==tr[tr[now].rc].c)tr[now].c=tr[tr[now].lc].c;else  tr[now].c=-1;}
}
void  change(int  now,int  l,int  r,int  k)
{if(tr[now].c==k)return  ;if(tr[now].l==l  &&  tr[now].r==r){tr[now].c=k;return  ;}int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(tr[now].c>0)tr[lc].c=tr[rc].c=tr[now].c;if(r<=mid)change(lc,l,r,k);else  if(mid+1<=l)change(rc,l,r,k);else  change(lc,l,mid,k),change(rc,mid+1,r,k);if(tr[lc].c==tr[rc].c)tr[now].c=tr[lc].c;else  tr[now].c=-1;
}
int  find(int  now,int  l,int  r)
{if(tr[now].c>0){if(cc!=tr[now].c){cc=tr[now].c;return  1;}else  return  0;}int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(r<=mid)return  find(lc,l,r);else  if(mid+1<=l)return  find(rc,l,r);else  return  find(lc,l,mid)+find(rc,mid+1,r);
}
int  main()
{scanf("%d%d",&n,&m);for(int  i=1;i<=n;i++)scanf("%d",&a[i]);bt(1,n);while(m--){int  x,y,k,z;scanf("%d%d%d",&k,&x,&y);if(x>y)swap(x,y);if(k==1){scanf("%d",&z);change(1,x,y,z);}else{cc=0;printf("%d\n",find(1,x,y));}}return  0;
}

4

【题目描述】 先是在数轴区间 0 到10^9 (10的9次方)之间画上了白色。然后,这个区间的某一些部分又画上了黑色。然后某一些部分又画上白色,等等。请你找出经历M(1 <= M <= 5000)次着色操作后,最长的白色区间。【输入格式】首行位M,以下M行位重着色的信息,每一行格式如下:ai bi ci 这里 ai ,bi 都是整数, ci 为字符'b' 或'w',用空格隔开。这三个参数描述:从ai到bi,着颜色ci, ('w'表示白,'b'表示黑),可以认为0 < ai <= bi < 10^9
【输出格式】输出x,y (x < y),之间用空格隔开,表示最长的白色区间。假如有多个答案,输出x最小的那个
【样例输入】
41 999999997 b40 300 w300 634 w43 47 b
【样例输出】
47 634这道题:线段树+离散化 PS:最开始1-10^9的染白不算在M次操作里面 

一道海星的题目,挺简单的,就实现复杂罢了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using  namespace  std;
struct  LSnode
{int  x,y,z;
}A[21000],B[21000];
int  K[21000];
struct  node
{int  l,r,lc,rc,c;
}tr[210000];int  len,m,kk,tt[21000],ans1,ans2,cc,tt1,tt2;
bool  cmp(LSnode  x,LSnode  y){return  x.x<y.x;}
void  bt(int  l,int  r)
{len++;int  now=len;tr[now].l=l;tr[now].r=r;tr[now].c=0;if(l+1<r){int  mid=(l+r)/2;tr[now].lc=len+1;bt(l,mid);tr[now].rc=len+1;bt(mid,r);}
}
void  change(int  now,int  l,int  r,int  k)
{if(tr[now].c==k)return  ;if(tr[now].l==l  &&  tr[now].r==r){tr[now].c=k;return  ;}int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(tr[now].c>=0)tr[lc].c=tr[rc].c=tr[now].c;if(r<=mid)change(lc,l,r,k);else  if(mid<=l)change(rc,l,r,k);else  change(lc,l,mid,k),change(rc,mid,r,k);if(tr[lc].c==tr[rc].c)tr[now].c=tr[lc].c;else  tr[now].c=-1;
}
void  find(int  now,int  l,int  r)
{if(tr[now].c>=0){if(cc!=tr[now].c){cc=tr[now].c;if(cc==0)tt1=l,tt2=tt[r]-tt[l];else  if(tt2>ans2){ans1=tt1,ans2=tt2;}}else{if(cc==0)tt2+=tt[r]-tt[l];}return  ;}int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;find(lc,l,mid);find(rc,mid,r);
}
int  main()
{scanf("%d",&m);for(int  i=1;i<=m;i++){char  ss[10];scanf("%d%d%s",&A[i*2-1].x,&A[i*2].x,ss);if(A[i*2-1].x>A[i*2].x)swap(A[i*2-1].x,A[i*2].x);A[i*2-1].z=i*2-1;A[i*2].z=i*2;B[i*2-1]=A[i*2-1];B[i*2]=A[i*2];if(ss[0]=='w')K[i]=0;else  K[i]=1;}sort(B+1,B+m*2+1,cmp);kk++;for(int  i=1;i<=m*2;i++){if(B[i].x!=B[i-1].x){kk++;tt[kk]=tt[kk-1]+(B[i].x-B[i-1].x);}A[B[i].z].y=kk;}if(B[m*2].x!=1000000000){kk++;tt[kk]=tt[kk-1]+(1000000000-B[2*m].x);}bt(1,kk);for(int  i=1;i<=m;i++){if(A[i*2-1].y!=A[i*2].y)change(1,A[i*2-1].y,A[i*2].y,K[i]);}find(1,1,kk);if(cc==0){if(tt2>ans2){ans1=tt1,ans2=tt2;}}printf("%d %d\n",tt[ans1],tt[ans1]+ans2);return  0;
}

5

【题目描述】远望城市的地平线,地平线上竖立着一些矩形的建筑物,现在要求知道这些矩形的覆盖面积(会有重叠面积,但不重复算,只算所有建筑物轮廓覆盖的面积)。所有矩形的下边与地平线重叠。现在有N个矩形,每个矩形给出 左边X坐标Ai和右边的X坐标Bi,和上边的Y坐标Hi(下边的Y坐标就是0)【范围】1 ≤ N ≤ 40,000 ,      0 ≤ Ai ≤ Bi ≤ 1,000,000,000,      1 ≤ Hi ≤ 1,000,000,000
【输入格式】第一行 N ,下来N行,每行三个整数 Ai, Bi, and Hi
【输出格式】一个整数,整个建筑群的轮廓覆盖的总面积。
Sample Input42 5 19 10 46 8 24 6 3Sample Output16
提示:3*1 + 1*4 + 2*2 + 2*3 - 1 = 16.

离散化,然后每个线段树的区间表示的是这个区间的轮廓。

#include<cstdio>
#include<cstring>
#include<algorithm>
using  namespace  std;
struct  node
{int  l,r,lc,rc,c;
}tr[210000];int  len,n;
struct  LSnode
{int  x,y,z;
}A[210000],B[210000];int  K[210000],kk,tt[210000];
bool  cmp(LSnode  x,LSnode  y){return  x.x<y.x;}
void  bt(int  l,int  r)
{len++;int  now=len;tr[now].l=l;tr[now].r=r;if(l+1<r){int  mid=(l+r)/2;tr[now].lc=len+1;bt(l,mid);tr[now].rc=len+1;bt(mid,r);}
}
void  change(int  now,int  l,int  r,int  k)
{if(tr[now].c>=k)return  ;if(tr[now].l==l  &&  tr[now].r==r  &&  tr[now].c>=0){tr[now].c=k;return  ;}int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(tr[now].c>=0)tr[lc].c=tr[rc].c=tr[now].c;if(r<=mid)change(lc,l,r,k);else  if(mid<=l)change(rc,l,r,k);else  change(lc,l,mid,k),change(rc,mid,r,k);if(tr[lc].c==tr[rc].c)tr[now].c=tr[lc].c;else  tr[now].c=-1;
}
int  find(int  now,int  l,int  r)
{if(tr[now].c>=0)return  tr[now].c*(tt[r]-tt[l]);int  lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;return  find(lc,l,mid)+find(rc,mid,r);
}
int  main()
{scanf("%d",&n);for(int  i=1;i<=n;i++){scanf("%d%d%d",&A[i*2-1].x,&A[i*2].x,&K[i]);A[i*2-1].z=i*2-1;A[i*2].z=i*2;B[i*2-1]=A[i*2-1];B[i*2]=A[i*2];}sort(B+1,B+n*2+1,cmp);kk=1;A[B[1].z].y=1;for(int  i=2;i<=n*2;i++){if(B[i].x!=B[i-1].x){kk++;tt[kk]=tt[kk-1]+B[i].x-B[i-1].x;}A[B[i].z].y=kk;}bt(1,kk);for(int  i=1;i<=n;i++){if(A[i*2-1].y!=A[i*2].y)change(1,A[i*2-1].y,A[i*2].y,K[i]);}printf("%d\n",find(1,1,kk));return  0;
}

小解区间操作

区间修改我们可以通过打懒标记的方式实现,什么是懒标记,就是当一个点的区间和我们要修改的样的时候,我们可以灵性的给他打个标记,然后在查询的时候在下传标记就行了。

区间查询我们早就会了。

二叉堆

例题

【题意】
给出n个正整数,输出最大的m个数。【输入格式】 第一行两个整数n和m(1<=n<=500000,1<=m<=5000)第二行给出n个整数(0<=a[i]<=100000)
【输出格式】按照从大到小的顺序输出。两数之间有空格。【样例输入】
5 32 4 5 1 3
【样例输出】
5 4 3 

思路

二叉堆的思路很简单,就是尽量构造一个完美二叉树,然后维护每个点的点权大(小)于自己的儿子节点,而且一个点\(x\)的父亲是\(x>>1\),儿子是\(x<<1\)和\((x<<1)+1\)。

然后加点就\(++len\),然后从下往上传。

\(POP\)就是把\(a[1]\)和\(a[len]\)交换一下,然后从\(1\)开始下传。

#include<cstdio>
#include<cstring>
#include<algorithm>
using  namespace  std;
int  a[210000],n,m;
void  heap(int  i)//自上往下的函数,自下往上的自己想想,十分简单
{int  j=i*2;while(j<=n){if(j<n  &&  a[j]<a[j+1])j++;if(a[j]>a[i]){swap(a[i],a[j]);i=j;j=i*2;}else  break;}
}
int  main()
{scanf("%d%d",&n,&m);for(int  i=1;i<=n;i++)scanf("%d",&a[i]);for(int  i=n/2;i>=1;i--)heap(i);//建堆for(int  i=1;i<m;i++){printf("%d ",a[1]);a[1]=a[n];n--;heap(1);}printf("%d\n",a[1]);return  0;
}

转载于:https://www.cnblogs.com/zhangjianjunab/p/11362396.html

线段树、二叉堆以及离散化入门相关推荐

  1. [十二省联考 2019] 异或粽子(可持久化字典树 + 二叉堆)

    problem luogu-P5283 小粽是一个喜欢吃粽子的好孩子.今天她在家里自己做起了粽子. 小粽面前有 nnn 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 111 到 nn ...

  2. 0x17.基础数据结构 - 二叉堆

    目录 一.二叉堆 二.例题 0.AcWing 145. 超市 AcWing 146. 序列(POJ 2442) 三.HuffmanHuffmanHuffman树 1.AcWing 148. 合并果子 ...

  3. 大根堆的删除c语言,二叉堆(一)之 C语言详解

    本文介绍二叉堆,二叉堆就是通常我们所说的数据结构"堆"中的一种.和以往一样,本文会先对二叉堆的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现: ...

  4. 在A*寻路中使用二叉堆

    在A*寻路中使用二叉堆 作者:Patrick Lester(2003年4月11日更新) 译者:Panic 2005年3月28日 译者序:     这一篇文章,是"A* Pathfinding ...

  5. 大顶堆删除最大值_算法学习笔记(47): 二叉堆

    堆(Heap)是一类数据结构,它们拥有树状结构,且能够保证父节点比子节点大(或小).当根节点保存堆中最大值时,称为大根堆:反之,则称为小根堆. 二叉堆(Binary Heap)是最简单.常用的堆,是一 ...

  6. 2021-10-21 二叉堆 恋上数据结构笔记

    文章目录 引言:Top K问题 堆 二叉堆 二叉堆的实现原理 二叉堆的添加原理 二叉堆的删除 批量建堆(自上而下的上滤与自下而上的下滤)及其效率对比 引言:Top K问题 堆 二叉堆 二叉堆的实现原理 ...

  7. java 二叉堆_二叉堆(三)之 Java的实现

    概要 前面分别通过C和C++实现了二叉堆,本章给出二叉堆的Java版本.还是那句话,它们的原理一样,择其一了解即可. 二叉堆的介绍 二叉堆是完全二元树或者是近似完全二元树,按照数据的排列方式可以分为两 ...

  8. python实现二叉堆中的大顶堆(大根堆)

    堆(英语:heap)是计算机科学中一类特殊的数据结构的统称.堆通常是一个可以被看做一棵树的数组对象.堆总是满足下列性质: 堆中某个节点的值总是不大于或不小于其父节点的值: 堆总是一棵完全二叉树. 将根 ...

  9. 构建二叉堆时间复杂度的证明

    http://blog.csdn.net/linuxtiger/article/details/7172258 如果仅从代码上直观观察,会得出构造二叉堆的时间复杂度为O(n㏒n)的结果,这个结果是错的 ...

最新文章

  1. 【HDU 5834】Magic boy Bi Luo with his excited tree
  2. daily scrum 11.1
  3. 音视频技术开发周刊 | 171
  4. windows2012同步linux时间,Windows server2012时间同步NTP配置
  5. 如何一键部署项目、代码自动更新
  6. Thinkphp内核无限坐席在线客服系统源码
  7. C#基础视频教程4.3 如何编写简单的计算器
  8. MySQL检测 explain解析
  9. hype-v的磁盘管理(转换)
  10. UI设计入门:解析设计标注规范和图标规范
  11. T-SQL 解析xml
  12. 计算机硬盘容量1t,硬盘1tb等于多少gb 硬盘容量计算公式
  13. 【2015NOIP模拟】【Ocd】【Mancity】【Captcha】10.31总结
  14. 探索Java中empty()与isEmpty()的区别
  15. Python处理气象信息grib,grib2文件
  16. oracle 日期改字符格式_Oracle时间转换成字符串
  17. 已经拿到CAD安装包,先别着急下载,快看看这些条件你的电脑满足了吗~
  18. C语言实现平衡二叉树-来源小甲鱼
  19. 外贸企业邮箱登录入口,怎么登陆邮箱app?
  20. mysql 小彬实战命令

热门文章

  1. Ubuntu安装webmin
  2. Linux 格式化扩展分区(Extended)
  3. 关于 继承、扩展和协议,深度好文
  4. MySQL installer
  5. 《Effective Java读书笔记》--序列化
  6. Android SDCard操作(文件读写,容量计算)
  7. 剑破冰山—Oracle开发艺术 前言
  8. Mysql+MHA高可用集群
  9. C#把某个数组的一部分复制到另一个数组中的两种方法:Buffer.BlockCopy和Array.Copy...
  10. python 程序1【登录接口】