冲击蓝桥杯-并查集,前缀和,字符串

Posted 川户

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了冲击蓝桥杯-并查集,前缀和,字符串相关的知识,希望对你有一定的参考价值。

目录

 前言

一、并查集

1、并查集的合并(带路径压缩)

2、询问是否为同一个集合

3、例题

二、前缀和

1 、前缀和是什么

2、经典题目

三- 字符串处理

1、字符串的插入

2、字符串转化为int类型

3、字符反转


 前言

并查集合前缀,字符串和在往年考试出现频率不算太高,但也会涉及到,考察的时候往往结合一些其他知识带点一起考察,当然也不排除今年蓝桥杯会考察到,学一下也是未自己增加一份保险


一、并查集

并查集,类似于树的组合,俩个数如何以最短的时间复杂度,实现合并,就是把一个树的根连到另一个树上去,时间复杂度近乎为1;

维护n个元素,刚开始每个元素自己一个集合,支持两个操作。

  • 合并两个元素所在的集合
  • 询问两个元素是否在相同的集合内

其他支持:

  • 维护每个元素和同一个集合内的其他元素的关系
  • 每个元素所在的集合的大小

并查集这个算法,他有自己的模板操作

1、并查集的合并(带路径压缩)

int find (int x)

    if(p[x]  != x )   p[x] = find(p[x]);   //父节点等于祖宗节点
    return p[x];

p[find(a)] = find(b);  //使a的祖宗节点的父节点等于b的父节点实现转接

2、询问是否为同一个集合

if(find(a) == find(b)) 

3、例题

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 100010;
int n,m;
int p[N];
int find (int x)

    if(p[x]  != x )   p[x] = find(p[x]);   //父节点等于祖宗节点
    return p[x];

int main()

    cin>>n>>m;
    for(int i = 1;i <= n; i ++)  p[i] = i;    //根据题目要求使得每个数各自在一个集合
    while(m--)
    
        char op[2];
        int a,b; 
        scanf("%s%d%d",op,&a,&b);  //输入字符串,因为scanf常常读入一些空格之类,使用字符串类型比较保险
    
        if(op[0] == 'M')   p[find(a)] = find(b);  //使a的祖宗节点的父节点等于b的父节点实现转接
        else 
           
           if(find(a) == find(b)) puts("Yes");
           else puts("No");
        
    
    return 0;

 2020蓝桥杯b组第四题考到DFS和并查集的内容,感兴趣可以尝试做一下真题


二、前缀和

1 、前缀和是什么

一维数组的前缀和很简单可以通过下面的例题来理解

2、经典题目

输入一个长度为 n的整数序列。

接下来再输入 m个询问,每个询问输入一对 l,r。

对于每个询问,输出原序列中从第 l个数到第 r 个数的和。

输入格式

第一行包含两个整数 n 和 m。

第二行包含 n 个整数,表示整数数列。

接下来 m 行,每行包含两个整数 l 和 r,表示一个询问的区间范围。

输出格式

共 m 行,每行输出一个询问的结果。

输入样例:

5 3
2 1 3 6 4
1 2
1 3
2 4

输出样例:

3
6
10

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int main()

    int n,m;
    int a[N],s[N] ;
    cin>>n>>m;
    for(int i =1;i <= n;i++) cin>>a[i];
    for(int i =1;i <= n;i++) s[i]= s[i-1] +a[i];
    while(m--)
    
        int l,r;
        cin>>l>>r;
        cout<<s[r] - s[l-1]<<endl;
    
 

三- 字符串处理

字符串题目考察频率也还行,学会简单的几个字符串STL的函数,可以帮助我们解决复杂的问题,

下面介绍几个
 

1、字符串的插入

string  s = "abcdef"

s1 =  s.substr (2)  //从下标为2的字符开始截取到结尾,s1 = "cdef";

s2 =  s.substr(2,3)  //从下标为2的2字符截取长度为3的字符串 s2 = "cde";

      

2、字符串转化为int类型

string 类型转化为int 型  stol()

string 类型转化为long long型 stoll()

代码

 string s = "12345";
 int t = stol(s);
 printf("%d\\n",t);
    
 long long m = stoll(s);
 printf("%lld",m);

3、字符反转

输入一个字符串,想使其反转过来

    string s;
    reverse(s.begin(),s.end());

蓝桥杯 修改数组 python (并查集)

蓝桥杯 修改数组 python (并查集)

题目描述

给定一个长度为 N N N 的数组 A = [ A 1 , A 2 , ⋅ ⋅ ⋅ , A N A_1,A_2,··· ,A_N A1,A2,,AN],数组中有可能有重复出现的整数。

现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改 A 2 , A 3 , ⋅ ⋅ ⋅ , A N A_2,A_3,··· ,A_N A2,A3,,AN

当修改 A i A_i Ai时,小明会检查$ A_i 是 否 在 是否在 A_1 ∼ A_i−1$现过。如果出现过,则小明会给 A i A_i Ai加上 1 ;如果新的 A i A_i Ai仍在之前出现过,小明会持续给 A i A_i Ai加 1 ,直 到 A i A_i Ai没有在 A 1 ∼ A i − 1 A_1 ∼ A_i−1 A1Ai1 中出现过。

A N A_N AN也经过上述修改之后,显然 A A A 数组中就没有重复的整数了。

现在给定初始的 A A A 数组,请你计算出最终的 A A A 数组。

输入描述

第一行包含一个整数 N N N

第二行包含 N N N 个整数 A 1 , A 2 , ⋅ ⋅ ⋅ , A N A_1,A_2,··· ,A_N A1,A2,,AN.

其中, 1 ≤ N ≤ 1 0 5 1 \\leq N \\leq 10^5 1N105 1 ≤ A i ≤ 1 0 6 1 \\leq A_i \\leq 10^6 1Ai106

输出描述

输出 N N N 个整数,依次是最终的 A 1 , A 2 , ⋅ ⋅ ⋅ , A N A_1,A_2,···,A_N A1,A2,,AN

输入输出样例

示例

输入

5
2 1 1 3 4

输出

2 1 3 4 5

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

思路

简单的思路可以利用哈希表,类似于bool数组,如果出现了,就进行了+1得到一个,如果发生矛盾了就需要遍历整个数组,在复杂的情况下,就需要n方的复杂度,对于很大的数据这就不太现实。

可以利用并查集,这样我们得到数据就只需要O(1)就解决了

首先设置一个father数组,这个数组所有的元素都指向自身,f[i]表示当你访问到 i 个数时应该把他换成什么

一开始都是f[ i ] 指向i ,也就说明都没访问过

当你访问了 i 以后,就需要进行更新,更新f[i] = f[i+1]

因为有时候有些数据是重复的,所以当我们再次访问到i的时候,i已经输出过了,这时候我们需要输出的i+1

但是这也涉及一个问题,i+1也有可能输出过了,所以说我们就输出的是f[i+1]

代码code

# https://www.lanqiao.cn/problems/185/learning/

import os
import sys

# 并查集 用于处理元素分组 寻找父亲
def find(x):
    global fa
    if fa[x] != x:
        fa[x] = find(fa[x])
    return fa[x]

N = int(input())
A = list(map(int,input().split()))

# 首先创建数组大小的并查集序列 自循环 全部指向自己
fa = [i for i in range(1000001)]

for i in range(N):
    # 找到A[i]元素父亲
    # 如果A[i]元素没有找到 则返回A[i]的值 同时将下一次查到A[i]值指向A[i]指向下一位
    # 如果A[i]找到 则继续增加
    # 2 1 1 3 4
    # 首先2 的父亲是2 并同时把父亲数组中A[i]位置元素修改为3,也就是再遇到2的时候,换为3
    # 其次为1 1的父亲是1 同时把父亲数组中1位置元素修改为2
    # 获得1 1的父亲此时为3 输出3 并将3的父亲修改为4
    # 获得3 3的父亲此时为4 输出4 并将此时3的父亲修改为5
    # 获得4 4的父亲此时为5 输出5 并将此时5的父亲修改为6
    A[i] = find(A[i])
    fa[A[i]] = find(A[i] + 1) # 更新为下一个点指向的点

for i in range(N):
    print(A[i], end=" ")

以上是关于冲击蓝桥杯-并查集,前缀和,字符串的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯之算法模板题 Python版

蓝桥杯 国王的烦恼 (并查集)

蓝桥杯 修改数组 python (并查集)

第四届蓝桥杯真题 连号区间

第十二届蓝桥杯 2021年国赛真题 (Java 大学B组)

蓝桥杯冲刺并查集专题