zoukankan      html  css  js  c++  java
  • 2020.10.2 清北学堂 J2综合强化营 D2 数据结构笔记

    数据结构

    (1).基础知识
    需要掌握:数组,链表,队列,栈,堆
    ((1)) 队列:FIFO(先进先出)
    ((2)) 栈:FILO(先进后出)

    (2).堆

    浅谈堆

    ((1)).实现:二叉树

    二叉树最简单的实现:一维数组
    二叉树编号法:设当前的节点编号为i,则其左儿子(2i) ,右儿子(2i+1)

    ((2)).分类

    大根堆:一个节点一定比它的两个儿子的权值大
    (所以求最大值直接返回根节点)

    小根堆:一个节点一定比它的两个儿子的权值小
    (所以求最小值直接返回根节点)

    ((3)).基本操作

    • 返回最值 ((max or min))
    • 删除(堆顶元素)任意元素
    • 插入一个元素
    strcut Heap{
    	int n;	//有n个数
    	int a[100010];	//这n个数存在了a[1~n];
    
    	inline int top{	//求最大值
    		return a[1];	
    	}
    	
    	inline void insert(int x){	//插入
    		a[++n]=x;	//放到最后
    		int p=n;
    		while(p>1 && a[p]>a[p/2]) swap(a[p],a[p/2]),p/=2;
    		//p>1 保证不是根节点
    		//a[p]>a[p/2] -> 如果当前节点比其父节点值大,不满足大根堆的要求,交换
    		//直至合法为止	
    	}
    
    	inline void delete(int q){
    		swap(a[q],a[n]);n--;	//删除a[q]
    		int p=1;
    		while(p*2<=n){	//左儿子存在
    			int pp=2*p;	//左儿子
    			if(pp+1<n &&a[pp+1]>a[pp]) pp++;
    			//如果右儿子也存在,且右儿子值比左儿子值大,指向右儿子
    			//如否,指向左儿子
    			//不管指向谁,都是较大的那个
    			if(a[p]<a[pp]){
    				swap(a[p],a[pp]);
    				p=pp;
    			}
    		}
    	}
    };
    

    (3).ST表

    浅谈ST表

    (ST)表是一种用于解决 (RMQ) (Range Minimum/Maximum Query,即区间最值查询)问题的算法

    以最小值为例:

    表示:令(f[i][j])表示从 (i) 开始 (2^j) 个数的最小值
    则显然 (f[i][0]=a[i]);

    转移:(f[i][j]=min(f[i][j-1],f[i+2^{j-1)}][j-1]));
    解释:根据 (2^j=2^{j-1} + 2^{j-1})
    (f[i][j-1]) -> 先从 (i)(2^{j-1}) 个数
    (f[i+2^{j-1}][j-1]) -> 现在的起始位置为上次走完 (2^{j-1}) 后的位置
    故为(i+2^{j-1}),再走(2^{j-1}),故(f[i+2^{j-1}][j-1])

    int main(){
    	cin>n;
    	for(int i=1;i<=n;i++) cin>>a[i];
    	for(int i=0;(1<<i)<=n;i++)
    		for(int j=(1<<i);j<(1<<(i+1));j++)	//j从2^i~2^(i+1)
    			use[j]=i;	//use[i] 表示用两个长度为use[i]的段盖住长度为i的段
    
    	for(int i=1;i<=n;i++) f[i][0]=a[i];	//初始化
    
    	for(int j=1;(1<<j)<=n;j++)
    		for(int i=1;(1<<i)<=n;i++)
    			f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    	//1<<j表示2^j,指1左移j位,得到的结果在十进制下为2^j
    
    	for(int i=1;i<=m;i++){
    		int l,r;
    		cin>>l>>r;	//左右端点
    		int len=r-l+1;	//[l,r]长度
    		int j=use[len];	
    		cout<<min(f[l][j],f[r-(1<<j)+1][j]);
    	}
    }
    

    (Practice):

    (Problem 1):给你 (N) 个数,求平均值最大的子区间
    (Solution Problem 1): 因为(从最大值开始)每加进来一个数平均值都会减小,所以其实答案就是数组里最大的那个数。

    (Problem 2):给你 (N) 个数,求(min(a_i,a_{i+1},...a_j) * |i-j|)的最大值 ((N<=10^5))

    (Problem 3):给定 (N) 个点,这 (N) 个点与 (N-1) 条边组成一个树。
    (M)次询问,每次询问给定(p1,p2)两点,问这两点之间的路径上有没有三个点,他们的点权可以构成一个三角形的三边。对于每一次询问,输出"YES"或"NO"

    (Problem 4):
    现有一个 (N*N) 的矩阵,其中有 (M) 个特殊点。
    两个点的距离定义为它们的曼哈顿距离。
    任意一个点的权值 指它到达每个特殊点的距离的最小值。
    ((1,1)) 走到 ((n,n)),求经过的权值的最小值最大是多少

    (Solution Problem 4):“最小值最大” -> 二分

    (4).单调队列

    有单调性的队列,即单调递减或单调递增的队列。

    浅谈单调队列
    struct Monotone_queue{
    	int q[100010];	//存队列元素
    	int head=1;tail=0;	//队头,队尾
    	void pop{      //Detele
    		head++;	
    	}
    	void push(int x){      //Add
    		while(head<tail && q[tail]>x) tail--;
    		//队列尾部的数比插入的数大,插入后无法保证单调性
    		//tail-- -> 相当于实现把队列尾部数弹出,直到合法
    		q[++tail]=x;	
    	}
    }
    

    (5).并查集

    浅谈并查集
    inline int find(int p){      
    	if(p=fa[p]) return p;
    	//return fa[p]=find(fa[p]);
    	int x=find(fa[p]);
    	fa[p]=x;
    	return x;		
    }
    inline void merge(int x,int y){
    	x=find(x);
    	y=find(y);
    	if(x==y) return;
    	fa[x]=y;
    }
    /*inline void merge(int x,int y){
          fa[find(x)]=find(y); 
    }
    */
    
  • 相关阅读:
    prototype.js超强的javascript类库
    MySQL Server Architecture
    Know more about RBA redo block address
    MySQL无处不在
    利用Oracle Enterprise Manager Cloud Control 12c创建DataGuard Standby
    LAMP Stack
    9i中DG remote archive可能导致Primary Database挂起
    Oracle数据库升级与补丁
    Oracle为何会发生归档日志archivelog大小远小于联机重做日志online redo log size的情况?
    Oracle Ksplice如何工作?How does Ksplice work?
  • 原文地址:https://www.cnblogs.com/-pwl/p/13763100.html
Copyright © 2011-2022 走看看