【基础算法模板梳理】再也不想学算法了!(待更新)

目录

1、【二分】

(1)r=mid —— 大于等于某数的最小值 

(2)l=mid —— 小于等于某数的最大值

2、【前缀和】

(1)一维前缀和

(2)二维前缀和

3、【差分】

(1)一维差分

(2)二维差分

4、【单调栈】

(1)单调递增栈

(2)单调递减栈

5、【并查集】

6、【BFS 求最短路】

为什么BFS可以求最短路?

7、【Dijkstra】

8、【spfa】

9、【floyd】

10、【kruskal】

11、【质数】

12、【约数】


1、【二分】

【蓝桥杯集训3】二分专题(3 / 5)-CSDN博客

  • l + r >> 1 —— 先 r = mid 后 l = mid+1 —— 寻找左边界 —— 找大于等于某数的最小值
  • l+r+1>>1 —— 先 l = mid 后 r = mid-1 —— 寻找右边界 —— 找小于等于某数的最大值

(1)r=mid —— 大于等于某数的最小值 

1 2 3 3 3 3 4 5

int l=0,r=n-1;

while(l>1;

    if(a[mid]>=x) r=mid;
    else l=mid+1;
}

(2)l=mid —— 小于等于某数的最大值

1 2 3 3 3 3 4 5

int l=0,r=n-1;

{
    int mid=l+r+1>>1;

    if(a[mid]<=x) l=mid;
    else r=mid-1;
}

2、【前缀和】

【蓝桥杯集训1】前缀和专题(4 / 5)-CSDN博客

(1)一维前缀和

a数组下标从1开始,Si = Si-1 + ai

则 [ Al,Ar ]段的和 = s[r] - s[l-1]

for(int i=1;i<=n;i++)
{
    a[i]=sc.nextInt();
    s[i]=s[i-1]+a[i];
}
        
[Al,Ar]的和 = s[r]-s[l-1]

(2)二维前缀和

【基础算法模板梳理】再也不想学算法了!(待更新)_第1张图片 

static int N=1010;
static int[][] a=new int[N][N],s=new int[N][N];
    
for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        a[i][j]=sc.nextInt();
        s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];
    }

【基础算法模板梳理】再也不想学算法了!(待更新)_第2张图片

while(q-->0)
{
    int x1=sc.nextInt(),y1=sc.nextInt(),x2=sc.nextInt(),y2=sc.nextInt();

    int res=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];

    System.out.println(res);
}

3、【差分】

【蓝桥杯集训2】差分专题(3 / 4)-CSDN博客

(1)一维差分

给a数组 [l,r] 区间的每个数+c,只需要给其差分数组b做如下操作即可

b[l]+=c;
b[r+1]-=c;

【基础算法模板梳理】再也不想学算法了!(待更新)_第3张图片

构造差分数组   \large b\left [ i \right ]=a\left [ i \right ]-a\left [ i-1 \right ]

int[] a=new int[N];
int[] b=new int[N];

for(int i=1;i<=n;i++)
{
    a[i]=sc.nextInt();
    b[i]=a[i]-a[i-1]; //构造差分数组
}

差分数组进行  \large b\left [ l \right ]+=c     操作

int l,r,c;
while(k-->0)
{
    b[l]+=c;
    b[r+1]-=c;
}

最后求差分数组b的前缀和即为原数组在【l,r】段+c的数组

for(int i=1;i<=n;i++)
{
    a[i]=a[i-1]+b[i]; //b的前缀和是a
    System.out.print(a[i]+" ");
}

(2)二维差分

【基础算法模板梳理】再也不想学算法了!(待更新)_第4张图片

【基础算法模板梳理】再也不想学算法了!(待更新)_第5张图片

 初始化

static int N=1010;
static int[][] a=new int[N][N],b=new int[N][N];
 
public static void work(int x1,int y1,int x2,int y2,int c)
{
    b[x1][y1]+=c;
    b[x2+1][y1]-=c;
    b[x1][y2+1]-=c;
    b[x2+1][y2+1]+=c;
}
 

for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        a[i][j]=sc.nextInt();
        work(i,j,i,j,a[i][j]);
    }
 

求前缀和

work(x1,y1,x2,y2,c);
 
for(int i=1;i<=n;i++)
{
    for(int j=1;j<=m;j++)
    {
        b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
        System.out.print(b[i][j]+" ");
    }
    System.out.println();
}

4、【单调栈】

【蓝桥杯集训9】单调栈、单调队列(模拟栈、模拟队列)专题(3 / 3)_Roye_ack的博客-CSDN博客

(1)单调递增栈

  • 在保持栈内元素单调递增前提下(如果栈顶元素大于待入栈元素,弹出栈顶),新元素入栈
  • 对于要入栈的元素,在对栈进行更新后,栈顶元素就是数组中左侧第一个比自己小的元素

【基础算法模板梳理】再也不想学算法了!(待更新)_第6张图片

(2)单调递减栈

  • 在保持栈内元素单调递减前提下(如果栈顶元素小于要待入栈元素,弹出栈顶),新元素入栈
  •  对于要入栈的元素,在对栈进行更新后,栈顶元素就是数组中左侧第一个比自己大的元素

【基础算法模板梳理】再也不想学算法了!(待更新)_第7张图片

题目:输出每个数左边第一个比自己小的数,如果不存在则输出-1 

class Main
{
    public static void main(String[] args)
    {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        Deque stk=new LinkedList<>();

        while(n-->0)
        {
            int x=sc.nextInt();

            while(!stk.isEmpty()&&stk.peek()>=x) stk.pop();

            if(stk.isEmpty()) System.out.print("-1 ");
            else System.out.print(stk.peek()+" ");

            stk.push(x);
        }
    }
}

 

5、【并查集】

【蓝桥杯集训7】并查集专题(3 / 5)-CSDN博客

int find(int x) //返回x的祖宗结点+状态压缩
{
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}
 
p[find(a)]=find(b); //合并操作 给a认个祖宗b
 
if(find(a)==find(b)) //a和b元素在同一个集合
 
for(int i=1;i<=n;i++) p[i]=i;
import java.util.*;
 
class Main
{
    static int N=100010;
    static int[] p=new int[N];
    
    public static int find(int x)
    {
        if(p[x]!=x) p[x]=find(p[x]); //如果不是祖宗,则向上查找
        return p[x];
    }
    
    public static void unite(int a,int b)
    {
        p[find(a)]=find(b); //给a认个祖宗b
    }
    
    public static void main(String[] args)
    {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt(),m=sc.nextInt();
        
        for(int i=1;i<=n;i++) p[i]=i;
        
        while(m-->0)
        {
            String s=sc.next();
            int a=sc.nextInt(),b=sc.nextInt();
            
            if(s.equals("M"))
            {
                if(find(a)!=find(b)) unite(a,b);
            }
            else 
            {
                if(find(a)==find(b)) System.out.println("Yes");
                else System.out.println("No");
            }
        }
    }
}

 

6、【BFS 求最短路】

【蓝桥杯集训11】BFS(4 / 4)_Roye_ack的博客-CSDN博客

为什么BFS可以求最短路?

为什么就算有多条通路,它总能输出最小距离?
因为当第一个点到达终点时,它一定是最短距离,并且会将终点标记,那么其他点再也无法到达终点,也更新不了初始点到终点的距离

将起点(0,0)入队,上下左右走,只要在合法的范围内且不碰到墙且没有走过,则入队

BFS就是将所有能走的路都走,第一条能走通的路一定是最短路

    static int[][] g=new int[110][110];
    static int[][] d=new int[110][110];  //记录该点到起点的最短距离
    static int[][] st=new int[110][110];  //标记走过的点
    static int[] dx={-1,1,0,0};
    static int[] dy={0,0,-1,1};    //方向数组
    public static int bfs()
    {
        d[0][0]=0;
        
        Queue q=new LinkedList<>();
        q.offer(new PII(0,0));
        
        while(!q.isEmpty())
        {
            PII t=q.poll();
            for(int i=0;i<4;i++)
            {
                int nx=t.x+dx[i];
                int ny=t.y+dy[i];
                if(nx>=0&&nx=0&&ny

 

7、【Dijkstra】

8、【spfa】

9、【floyd】

10、【kruskal】

11、【质数】

12、【约数】

你可能感兴趣的:(蓝桥杯集训,蓝桥杯真题,算法,蓝桥杯,前缀和,差分,单调栈,图论,质数)