1.第K个数
思路:
代码:
#include<iostream>
using namespace std;
const int N = 10010;
int n, k;
int q[N];
int quick_sort(int l, int r, int k) {
if (l >= r) {
return q[l];
}
int i = l - 1, j = r + 1,x=q[l+r>>1];
while (i < j) {
do {
i++;
} while (q[i] < x);
do{
j--;
}while (q[j] > x);
if (i < j) {
swap(q[i], q[j]);
}
}
int sl = j - l + 1;
if (k<=sl) {
//递归左区间
return quick_sort(l, j, k);
}
return quick_sort(j + 1, r, k-sl);
}
int main(void) {
cin >> n >> k;
for (int i = 0; i < n; i++) {
cin >> q[i];
}
cout << quick_sort(0, n - 1, k) << endl;
return 0;
}
2.逆序对个数
思路:
mid就是分界点
代码:
#include<iostream>
using namespace std;
const int N = 100010;
int q[N], tmp[N];
int n;
long long merge_sort(int l, int r) {
if (l >= r) {
return 0;
}
int mid = l + r >> 1;
long long 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[i] <= q[j]) {
tmp[k++] = q[i++];
}
else {
tmp[k++] = q[j++];
res += mid - i + 1;
}
}
while (i <= mid) {
tmp[k++] = q[i++];
}
while (j <= r) {
tmp[k++] = q[j++];
}
for (int i = l, j = 0; i <= r; i++, j++) {
q[i] = tmp[j];
}
return res;
}
//6
//2 3 4 5 6 1
int main(void) {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> q[i];
}
cout << merge_sort(0, n - 1) << endl;
return 0;
}
3.数的三次方根
很普通的一道二分查找,直接贴代码:
#include<iostream>
using namespace std;
#define eps 1e-8
int main(void) {
double x;
cin >> x;
double l = -10000, r = 100000;
while (r - l > eps) {
double mid = (l + r) / 2;
if (mid * mid * mid >= x) {
r = mid;
}
else {
l = mid;
}
}
printf("%lf", l);
return 0;
}
4.前缀和
代码:
#include<iostream>
using namespace std;
const int N = 100010;
int n,m;
int a[N], s[N];
int main(void) {
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;
}
return 0;
}
5.子矩阵之和(二维前缀和)
直接套公式,代码:
#include<iostream>
using namespace std;
const int N = 1010;
int a[N][N], s[N][N];
int n, m, q;
int main(void) {
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++) {
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
}
}
while (q--) {
int x1, y1, x2, y2;
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
printf("%d\n", s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]);
}
return 0;
}
6.差分
差分就是前缀和的逆运算
代码:
#include<iostream>
using namespace std;
const int N = 10010;
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(void) {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
//构造差分数组
for (int i = 1; i <= n; i++) {
insert(i, i, a[i]);
}
while (m--) {
int l, r, c;
scanf("%d %d %d", &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]);
}
return 0;
}
7.差分矩阵
#include<iostream>
using namespace std;
const int N = 1010;
int a[N][N], b[N][N];
int n, m, q;
void insert(int x1, int y1, int x2, int y2, int c) {
b[x1][y1] += c;
b[x1][y2+1] -= c;
b[x2+1][y1] -= c;
b[x2 + 1][y2 + 1] += c;
}
int main(void) {
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, x2, y1, 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]);
}
printf("\n");
}
return 0;
}