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); 
    }
    */
    
  • 相关阅读:
    原型设计作业
    案例分析作业
    编程作业
    阅读任务
    自我介绍
    5 20210420-1 团队作业1—团队展示
    3 20210405-1 案例分析作业
    阅读任务
    自我介绍
    原型设计
  • 原文地址:https://www.cnblogs.com/-pwl/p/13763100.html
Copyright © 2011-2022 走看看