文章目录

  • 786.求第k个数
  • 788.逆序对的数量
  • 790.数的三次方根
  • 795.前缀和
  • 796.子矩阵的和 (二维前缀和 + 容斥原理)
  • 797.差分 (前缀和的逆运算)
  • 798.差分矩阵

786.求第k个数

给定一个长度为n的整数数列,以及一个整数k,请用快速选择算法求出数列的第k小的数是多少。
输入格式
第一行包含两个整数 n 和 k。第二行包含 n 个整数(所有整数均在1~109范围内),表示整数数列。
输出格式
输出一个整数,表示数列的第k小数。
数据范围
1≤n≤100000,1≤k≤n
输入样例:
5 3
2 4 1 5 3
输出样例:
3

快速选择算法
1.找到分界点x,q[L],q[(L + R) / 2] , q[R]
2.左边所有数left <= x,右边所有数 >= x
3.递归排序left,递归排序right
①k <= sl(S-left-length) ,递归left(第k个在左边)
②k > sl ,(递归right)


#include <iostream>
using namespace std;const int N = 100010;  //多10 比如 防止数组下标越界
int n,k;
int q[N];int quick_sort(int l,int r,int k){if(l >= r) return q_01[l]; //找到   快排必须写 >=  因为最终可能没有数满足 int x = q[l], i = l - 1,j = r + 1;  //快排边界区间在两侧 while(i < j){while(q_01[++i] < x);while(q_01[--j] > x);if(i < j) swap(q[i] , q[j]);    }int sl = j - l + 1; if(k <= sl) return quick_sort(l,j,k_01); //第k个数在左边区间 return quick_sort(j + 1,r,k - sl);//k - sl为右区间的第几个 } /* n_01 k_01 数组
5 3
2 4 1 5 3
*/
int main(){cin >> n_01 >> k_01;for(int i = 0;i < n_01;i++){cin >> q_01[i]; } cout << quick_sort(0,n_01 - 1,k_01) << endl;return 0;
} 

788.逆序对的数量

题目:
给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量。
逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i<j 且 a[i]>a[j],则其为一个逆序对;否则不是。
输入格式
第一行包含整数 n,表示数列的长度。
第二行包含 n 个整数,表示整个数列。
输出格式
输出一个整数,表示逆序对的个数。
数据范围
1≤n≤100000 (极限 全部逆序 , n + n - 1 + … + 1 = n * (n - 1) / 2 == 1012 / 2 > int 232 -->long long)
输入样例:
6
2 3 4 5 6 1
输出样例:
5

定义:每两个数比较 , 前面的数比后面的数大 , 则为一个逆序对
归并排序:

  1. [L,R] => [L,mid],[mid + 1,R]
  2. 归并排序 [L,mid] 和 [mid + 1, R]
    3.归并排序 ,将左右两个有序序列合并成一个有序序列
    逆序对比较三种情况 :
    ①都在左半边 merge_sort(L,mid)
    ②一个左半边,一个右半边
    ③都在右半边 merge_sort(mid+1,r)

typedef long long LL;
int n_02;
int q_02[N],tmp_02[N];LL merge_sort(int l,int r){if(l >= r) return 0;int mid = l + r >> 1;LL res = merge_sort(l,mid) + merge_sort(mid+1,r); //排序结果相加 //归并的过程int k = 0,i = l,j = mid + 1;//两个指针 头 和 中间  -->分段比较排序 -- 小的放前面一段 while(i <= mid && j <= r){  if(q_02[i] <= q_02[j]) tmp_02[k++] = q_02[i++];else{ tmp_02[k++] = q_02[j++];res += mid - i + 1;   //分别在左右边已经排好序的情况③,当大于1个数即比这个数后面的数都大的区间 res要 += 此情况的逆序对个数 }                                       //扫尾 (没遍历完的接在后面)while(i <= mid) tmp_02[k++] = q_02[i++];while(j <= r) tmp_02[k++] = q_02[j++];} //物归原主 for(int i = l, j = 0;i <= r;i++,j++){   //q_02数组的区间 [l,r]   tmp_02[j]从0开始按位置放q_02[i] q_02[i] = tmp_02[j];       } return res;
}int main(){cin >> n_02;for(int i = 0;i < n_02;i++){cin >> q_02[i];}cout << merge_sort(0 , n_02 - 1) << endl;return 0;
}

790.数的三次方根

给定一个浮点数n,求它的三次方根。
输入格式
共一行,包含一个浮点数n。
输出格式
共一行,包含一个浮点数,表示问题的解。
注意,结果保留6位小数。
数据范围
-10000≤n≤10000
输入样例:
1000.00
输出样例:
10.000000

int main(){double x;cin >> x;double l = -10000,r = 10000;while(r - l > 1e-8){double mid = (l + r) / 2;if(mid * mid * mid >= x) r = mid;else l = mid ;}printf("%lf\n",l);//lf默认保留6位小数 ,也可以加 .6 return 0;
} 

795.前缀和

输入一个长度为n的整数序列。
接下来再输入m个询问,每个询问输入一对l, r。
对于每个询问,输出原序列中从第l个数到第r个数的和。
输入格式
第一行包含两个整数n和m。
第二行包含n个整数,表示整数数列。
接下来m行,每行包含两个整数l和r,表示一个询问的区间范围。
输出格式
共m行,每行输出一个询问的结果。
数据范围
1≤l≤r≤n,
1≤n,m≤100000,
-1000≤数列中元素的值≤1000
输入样例:
5 3
2 1 3 6 4
1 2
1 3
2 4
输出样例:
3
6
10

一维前缀和:
1 . Si = a1 + a2 + … + ai
2. sum(L,R) = aL + aL+1 + aL+2 + … + aR = S[k] - S[i-1]
1.预处理前缀和数组
2.用公式求区间和
重要总结凡是数组有用到下标i-1的都从1开始定义 ! dp / hash / dfs等

int a_04[N],s_04[N];
int main(){int n,m;cin >> n >> m;for(int i = 1;i <= n;i++){cin >> a_04[i];}//求前缀和数组 for(int i = 1;i <= n;i++){ //dp 等于之前的+当前值 s_04[i] = s_04[i - 1] + a_04[i];} while(m--)//m次询问求前缀和 {int l,r; //输入查询区间 cin >> l >> r;cout << s_04[r] - s_04[l - 1] << endl; //差值即可 }return 0;
}

796.子矩阵的和 (二维前缀和 + 容斥原理)

输入一个n行m列的整数矩阵,再输入q个询问,每个询问包含四个整数x1, y1, x2, y2,表示一个子矩阵的左上角坐标和右下角坐标。
对于每个询问输出子矩阵中所有数的和。
输入格式
第一行包含三个整数n,m,q。
接下来n行,每行包含m个整数,表示整数矩阵。
接下来q行,每行包含四个整数x1, y1, x2, y2,表示一组询问。
输出格式
共q行,每行输出一个询问的结果。
数据范围
1≤n,m≤1000,
1≤q≤200000,
1≤x1≤x2≤n,
1≤y1≤y2≤m,
?1000≤矩阵内元素的值≤1000
输入样例:
3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
2 1 3 4
1 3 3 4
输出样例:
17
27
21

思路:
1.s[i,j]如何计算
2.(x1,x2),(x2,y2) 分别子矩阵为左上角和右下角坐标
3. sx2,y2 = s[x1,y1](大到边界) - s[x1 - 1,y2] - s[x2,y1 - 1] + s[x1 - 1, y1 -1]
(s[x2,y2]指x2*y2的矩阵 ,其他同理 ,思想:大矩阵 - 边界的矩阵(分3个部分) + 重复多减的部分)
画图推导dp s[i,j] = s[i-1,j] + s[i,j-1] - s[i-1,j-1] + a[i,j]


#include<cstdio>int n_05,m_05,q_05;
int a_05[1010][1010],s_05[1010][1010];  //数组 1e12 空间直接炸
int test_05(){scanf("%d%d%d",&n_05,&m_05,&q_05);for(int i = 1;i <= n_05;i++){for(int j = 1;j <= m_05;j++){scanf("%d",&a_05[i][j]); }}//初始化前缀和数组for(int i = 1;i <= n_05;i++){for(int j = 1;j <= m_05;j++){s_05[i][j] = s_05[i - 1][j] + s_05[i][j-1] - s_05[i - 1][j-1]  + a_05[i][j]; //初始化前缀和}}//询问次数 while(q_05--){int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);printf("%d\n_05",s_05[x2][y2] - s_05[x2][y1 -1] - s_05[x1 - 1][y2] + s_05[x1 - 1][y1 - 1]);  //【容斥原理 减去边界】// x1 - 1对应y2 , x2对应y1 - 1 ,再加回 记忆 } return 0;
}

797.差分 (前缀和的逆运算)

输入一个长度为n的整数序列。
接下来输入m个操作,每个操作包含三个整数l, r, c,表示将序列中[l, r]之间的每个数加上c。
请你输出进行完所有操作后的序列。
输入格式
第一行包含两个整数n和m。
第二行包含n个整数,表示整数序列。
接下来m行,每行包含三个整数l,r,c,表示一个操作。
输出格式
共一行,包含n个整数,表示最终序列。
数据范围
1≤n,m≤100000,
1≤l≤r≤n,
-1000≤c≤1000,
-1000≤整数序列中元素的值≤1000
输入样例:
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
输出样例:
3 4 5 3 4 2

差分思想: 时间复杂度变成O(1)
给定 a[1],a[2],a[3],a[4] … a[n]
构造差分数组 b[N] ,使得
a[i] = b[1] + b[2] + … b[i] (a[i]是b数组的前缀和
差分核心操作:将a[L~R] 全部加上C,等价于让b[L] += C ,b[R + 1] -= C; C是∑a[L~R]
1.a[1~L-1]无影响
2.a[L~R]加上了C
3.a[R+1,N]无影响 (注意数组a的值是指 [ ∑b[0~R+1] , ∑b[0~N] ] 区间值无影响(包括了加减C)!
(看做在b数组上进行了n次的插入操作)
在b数组上 加减C,b的前缀和a整体求和b来看 是抵消不变 ,但有些段受影响 (即满足1. && 2. && 3. 就可以实现差分了)
如b[R+1] -= C ,a[L~R]在[ ∑b[0~L] , ∑b[0~R] ]值加C (R+1才减C) ,前缀和a[R+1~N]包括了b[R+1]不受影响-值不变
而前缀和a[1~L-1]即不包括b[L]又不包括b[R+1] ,完全没有影响 --等效完成了前缀和数组a的差分

int n ,m;
int a[N],b[N]; void insert(int l,int r,int c){b[l] += c;b[r + 1] -= c;}
int main(){cin >> n >> m;for(int i = 1;i<= n;i++){cin >> a[i];}for(int i = 1;i <= n;i++){insert(i,i,a[i]);}while(m--){int l,r,c;cin >> l >> r >> c;insert(l,r,c);}for(int i = 1;i <= n;i++) a[i] = a[i - 1] + b[i];for(int i = 1;i <= n;i++) printf("%d ",a[i]);puts("");return 0;
} 

798.差分矩阵

输入一个n行m列的整数矩阵,再输入q个操作,每个操作包含五个整数x1, y1, x2, y2, c,其中(x1, y1)和(x2, y2)表示一个子矩阵的左上角坐标和右下角坐标。
每个操作都要将选中的子矩阵中的每个元素的值加上c。
请你将进行完所有操作后的矩阵输出。
输入格式
第一行包含整数n,m,q。
接下来n行,每行包含m个整数,表示整数矩阵。
接下来q行,每行包含5个整数x1, y1, x2, y2, c,表示一个操作。
输出格式
共 n 行,每行 m 个整数,表示所有操作进行完毕后的最终矩阵。
数据范围
1≤n,m≤1000,
1≤q≤100000,
1≤x1≤x2≤n,
1≤y1≤y2≤m,
-1000≤c≤1000,
-1000≤矩阵内元素的值≤1000
输入样例:
3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
1 1 2 2 1
1 3 2 3 2
3 1 3 4 1
输出样例:
2 3 4 1
4 3 4 1
2 2 2 2

给定原矩阵a[i,j],构造差分矩阵 b[i,j],使得a[][]是b[][]的二维前缀和
差分核心操作:给以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵的所有数a[i,j] ,加上C 【包含这个格子的大矩阵都被影响要+C】
对于差分数组的影响:
b[x1][y1] += c;//x1,y1之前的矩阵+C
b[x1][y2+1] -= c; //旁边的矩阵不受影响
b[x2+1][y1] -= c;
b[x2+1][y2+1] += c;//x2,y2之后的大矩阵不受影响 【 ±± C == 0 】
a[i][j] = a[i - 1][j] + a[i][j - 1] - a[i - 1][j -1] + b[i][j]; //二维前缀和公式


#include<cstdio>
int n,m,q;
int a[1010][1010],b[1010][1010]; //差分操作
void insert(int x1,int y1,int x2,int y2,int c){b[x1][y1] += c;//x1,y1之前的矩阵+C b[x1][y2+1] -= c; //旁边的矩阵不受影响 b[x2+1][y1] -= c; b[x2+1][y2+1] += c;//x2,y2之后的大矩阵不受影响  +--+ C == 0
}int main(){scanf("%d%d%d",&n,&m,&q);for(int i = 1;i <= n;i++){for(int j = 1;j <= m;j++){scanf("%d",&a[i][j]);}} for(int i = 1;i <= n;i++){for(int j = 1;j <= m;j++){insert(i,j,i,j,a[i][j]);   }}//询问 while(q--){int x1,y1,x2,y2,c;scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);insert(x1,y1,x2,y2,c); }for(int i = 1;i <= n;i++){for(int j = 1;j <= m;j++){a[i][j] = a[i - 1][j]  + a[i][j - 1] - a[i - 1][j -1] + b[i][j];  //二维前缀和公式  }}for(int i = 1;i <= n;i++){for(int j = 1;j <= m;j++){printf("%d ",a[i][j]);}puts(""); }return 0;
} 

蓝桥杯_算法基础练习week-practice相关推荐

  1. 蓝桥杯_算法训练_ALGO12_摆动序列

    问题描述 如果一个序列满足下面的性质,我们就将它称为摆动序列: 1. 序列中的所有数都是不大于k的正整数: 2. 序列中至少有两个数. 3. 序列中的数两两不相等: 4. 如果第i – 1个数比第i ...

  2. 蓝桥杯_算法训练_矩阵乘法

    问题描述 输入两个矩阵,分别是m*s,s*n大小.输出两个矩阵相乘的结果. 输入格式 第一行,空格隔开的三个正整数m,s,n(均不超过200). 接下来m行,每行s个空格隔开的整数,表示矩阵A(i,j ...

  3. ALGO-22_蓝桥杯_算法训练_数的划分(DP)

    问题描述将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序).例如:n=7,k=3,下面三种分法被认为是相同的.1,1,5; 1,5,1; 5,1,1;问有多少种不同的分法. 输入格式n, ...

  4. 蓝桥杯_算法训练_ALGO10_集合运算

    这个题实际上思路是比较简单的,但是需要注意细节问题. 思路:读入数组之后进行排序,然后再求交.并.补集. 首先排序:(使用的是冒泡排序) 1 #include<iostream> 2 us ...

  5. 蓝桥杯_算法训练_Torry的困惑(基本型)

    这个题目就是求质数的乘积,在加一个模,思路比较简单,直接上代码: 1 #include<iostream> 2 using namespace std; 3 bool isPrime(in ...

  6. 蓝桥杯_算法训练_关联矩阵

    这个题目首先我们要知道关联矩阵是什么: 这个是网上找到的关联矩阵的定义,个人感觉还是比较清楚的. 好,那接下来就是根据所给的数据进行矩阵的输出. 题目中给的是有向图,定义中的是无向图.二者的区别大家应 ...

  7. 蓝桥杯_算法训练_最小乘积(基本型)

    问题描述 给两组数,各n个. 请调整每组数的排列顺序,使得两组数据相同下标元素对应相乘,然后相加的和最小.要求程序输出这个最小值. 例如两组数分别为:1 3 -5和-2 4 1 那么对应乘积取和的最小 ...

  8. 蓝桥杯_算法训练_字串统计

    其实题目已经给的很清楚了,枚举所有的情况,统计出现次数,找到符合条件的结果. 那么我们就根据这个提示完成即可: 第一步:枚举所有可能的字串: 1 #include<iostream> 2 ...

  9. 蓝桥杯_算法训练_表达式计算

    之前在学习栈的时候老师讲过这个问题 思路就是: 1.将表达式(中缀式)转化成后缀式: 2.进行后缀式的计算. 思路看起来很简单,但是实际在敲代码的时候还是要注意很多问题.下面分享一下个人做法,可以改进 ...

最新文章

  1. SpringBoot实现热部署(修改class不需要重启)
  2. mysql 主键 uniqo_项目总结,彻底掌握NodeJS中如何使用Sequelize
  3. OpenGL开发学习指南一(freeglut+glew)
  4. LeetCode 2114. 句子中的最多单词数
  5. matlab函数输出,优化求解器输出函数
  6. 事务ACID理解复习
  7. 《哪吒之魔童降世》电影密钥延期至9月26日,将冲击中国票房总榜前三
  8. java猜单词游戏_9 java基础综合编程练习---猜单词游戏
  9. 基于JAVA+Servlet+JSP+MYSQL的教室预订管理系统
  10. ribbon 配置 动态更新_Netflix开源工具:在SpringBoot实现动态路由
  11. 激活golang编辑器
  12. 使用python实现可视化ftp客户端(本地文件展示和搜索功能、ftp文件展示和搜索功能以及上传和下载功能)
  13. Zookeeper如何保证数据一致性
  14. 618网购盛宴即将开启,云联络中心+AI成为电商的“新基建”
  15. 自然辩证法(研究生)期末考试题库
  16. html设置首缩选进两字符,首行缩进2字符怎么设置 css
  17. HE4484E原厂升压8.4v锂电池充电芯片
  18. FastDfs分布式文件存储系统
  19. android开发艺术探索3:IPC--AIDL(跨进程)的使用
  20. 一个简单的页面加载管理类(包含加载中,加载失败,数据为空,加载成功)

热门文章

  1. java薄弱基础知识记录
  2. Paint 全面解析
  3. 利用Python进行破解哔哩哔哩登录
  4. 三个在线生成.ico图片的网站
  5. css 与 html5
  6. 中信国健临床通讯2011年11月期ACR会议进展目录
  7. “数”造城市 “智”造未来
  8. C#-graphic-中在PictureBox上使用橡皮筋画线
  9. Conda安装pytorch等库时下载速度慢的解决方案(离线下载)
  10. 网络扫描和网络侦察实验报告