#include<iostream> usingnamespace std; constint N = 1e6 + 10 ;//一后面6个零,应该是1e6 + 10 int n; int q[N]; voidquick_sort(int q[], int l, int r) { if (l >= r) return; int x = q[(l + r) / 2], i = l - 1, j = r + 1; // 注意快速排序这道题目的数据已加强,划分中点取左端点或右端点时会超时,改成取中点或者随机值即可。 // 每次交换玩指针都要往中间移动一格, // 因此后面循环是这样做的, // 每次不管三七二十一, // 先把指针往中间移动一格, // 然后再去判断,因此两个指针都要放在左右两个边界的左右一格, // 这样我们往中间移动一格之后才是真正的边界 // 所以才有一个偏移量,需要往两边扩一格 // int x = q[(l + r) / 2]; // int x = q[r]; while (i < j) { do i++; while (q[i] < x); do j--; while (x < q[j]); if (i < j) swap(q[i], q[j]); }
quick_sort(q, l, j); quick_sort(q, j + 1, r); } intmain(void) { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &q[i]);
quick_sort(q, 0, n - 1);
for (int i = 0; i < n; i++) printf("%d ", q[i]); return0; }
#include<iostream> usingnamespace std; constint N = 1e6 + 10; int n; int q[N]; voidquick_sort(int q[], int l, int r) { if (l >= r) return; int x = q[(l + r) / 2], i = l - 1, j = r + 1; while (i < j) { do i++; while (q[i] < x); do j--; while (x < q[j]); if (i < j) swap(q[i], q[j]); }
quick_sort(q, l, j); quick_sort(q, j + 1, r); } intmain(void) { scanf("%d", n);//错误 for (int i = 0; i < n; i++) { scanf("%d", &q[i]); } quick_sort(q, 0, n - 1);
for (int i = 0; i < n; i++) { printf("%d ", q[i]); } return0; }
#include<iostream> usingnamespace std; constint N = 100010; int n; int q[N]; voidquick_sort(int q[], int l, int r);
intmain(void) { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &q[i]); quick_sort(q, 0, n - 1); for (int i = 0; i < n; i++) printf("%d ", q[i]); return0; } voidquick_sort(int q[], int l, int r) { if (l >= r) return; // 这是一个疑点,我认为是l >= r 的原因是当l == r的时候一个元素组成的序列就是有序的,所以你不用再递归下去了,这就是最后一层递归了,直接返回上一层就行 int x = q[(l + r) / 2], i = l - 1, j = r + 1; // 个人记忆口诀,快排和归并排序都用到i和j来对数组q[] 的当下这一层递归的部分 也就是l 到 r这一部分进行处理 // 同时不能改变l 和 r的值,因为要作为实参传给下一层递归,所以用借用i和j // 二分查找就不需要i和j,因为直接在while循环里面更新l = mid或者 r = mid来让区间缩小 while (i < j) { // 个人记忆口诀,对于快拍而言,因为这个while循环条件是i < j,所以递归终止条件是if (i >= j) do i++; while (q[i] < x); do j--; while (q[j] > x); if (i < j) // 不能忘了这个if,因为很可能你找到i和j后就已经不满足i < j的条件了, // 我记得y总一开始举的数组序列的例子就是第一次找到的i和j之后,发现i >= j了 swap(q[i], q[j]); }
quick_sort(q, l, j); quick_sort(q, j + 1, r); }
疑点1
1 2
if (l >= r) return; // 这是一个疑点,我认为是l >= r 的原因是当l == r的时候一个元素组成的序列就是有序的,所以你不用再递归下去了,这就是最后一层递归了,直接返回上一层就行
查找第一次写的代码就是if(l >= r),个人认为的原因就是我上面的注释
疑点2
1 2 3 4 5 6
int x = q[(l + r) / 2], i = l - 1, j = r + 1; // 个人记忆口诀,快排和归并排序都用到i和j来对数组q[] 的当下这一层递归的部分 也就是l 到 r这一部分进行处理 // 同时不能改变l 和 r的值,因为要作为实参传给下一层递归,所以用借用i和j // 二分查找就不需要i和j,因为直接在while循环里面更新l = mid或者 r = mid来让区间缩小 while (i < j) { // 个人记忆口诀,对于快拍而言,因为这个while循环条件是i < j,所以递归终止条件是if (i >= j)
疑点3
1 2 3 4
if (i < j) // 不能忘了这个if,因为很可能你找到i和j后就已经不满足i < j的条件了, // 我记得y总一开始举的数组序列的例子就是第一次找到的i和j之后,发现i >= j了 swap(q[i], q[j]);
constint N = 100010; int n; int q[N]; voidquick_sort(int q[], int l, int r); intmain(void) { scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &q[i]); } quick_sort(q, 0, n - 1); for (int i = 0; i < n; i++) { printf("%d ", q[i]); } return0; } voidquick_sort(int q[], int l, int r) { if (l >= r) return; int x = q[(l + r) / 2], i = l - 1, j = 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]); } quick_sort(q, l, j); quick_sort(q, j + 1, r); }
#include<iostream> usingnamespace std; constint N = 100010; int n; int q[N]; voidquick_sort(int q[], int l, int r);
intmain(void) { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &q[i]);
quick_sort(q, 0, n - 1); for (int i = 0; i < n; i++) printf("%d ", q[i]);
return0; } voidquick_sort(int q[], int l, int r) { if (l >= r) return; int x = q[(l + r + 1) / 2], i = l - 1, j = r + 1; while (i < j) { do i++; while (q[i] < x); // 这里推荐用快排是不稳定的排序来记忆,所以在x左边等于x的数可能被交换到x的右边 do j--; while (q[j] > x); if (i < j) swap(q[i], q[j]); } // quick_sort(q, l, j); // j的话就不能右边界 // quick_sort(q, j + 1, r);
quick_sort(q, l, i - 1); quick_sort(q, i, r); // i的话就不能取左边界
#include<iostream> usingnamespace std; constint N = 1000010; int n; int q[N], tmp[N]; voidmerge_sort(int q[], int l, int r) { if (l >= r) return; int mid = l + r >> 1;//这里还是写成l + r >> 1的好,能避免和y总不一致的问题,具体原因我没时间管了. merge_sort(q, l, mid); merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1; // k表示当前辅助数组tmp里面有多少个数了,已经合并多少个数了 // i指向第一个序列的起点 // j指向第二个序列的起点 while (i <= mid && j <= r) { if (q[i] <= q[j]) tmp[k++] = q[i++]; else tmp[k++] = q[j++]; } while (i <= mid) tmp[k++] = q[i++]; while (j <= r) tmp[k++] = q[j++];
for (i = l, j = 0; i <= r; i++, j++) q[i] = tmp[j]; } intmain(void) { scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &q[i]); } merge_sort(q, 0, n - 1); for (int i = 0; i < n; i++) { printf("%d ", q[i]); } return0; }
1103T1
犯的错误1
1
int mid = l + r >> 2;//写错了,应该是右移一位等于除以2
应该写成
1
int mid = l + r >> 1;//写错了,应该是右移一位等于除以2
犯的错误2
1 2 3 4 5
while (i <= mid && j <= r) if (q[i] < q[j])//q[i] <= q[j] tmp[k++] = q[i++]; else tmp[k++] = q[j++];
为了保证归并的稳定性,应该写成
1 2 3 4 5
while (i <= mid && j <= r) if (q[i] <= q[j])//q[i] <= q[j] tmp[k++] = q[i++]; else tmp[k++] = q[j++];
#include<iostream> usingnamespace std; constint N = 1000010;//写错了,应该少些一个0 int n; int q[N], tmp[N]; voidmerge_sort(int q[], int l, int r) { if (l >= r) return; int mid = l + r >> 2;//写错了,应该是右移一位等于除以2 merge_sort(q, l, mid); merge_sort(q, 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++]; 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里面去. q[i] = tmp[j]; } intmain(void) { scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &q[i]); } merge_sort(q, 0, n - 1); for (int i = 0; i < n; i++) { printf("%d ", q[i]); } return0; }
#include<iostream> usingnamespace std; constint N = 100010; int n; int q[N]; // 记录自己每一次不太确定的部分,好像是N,不是n boolcheckStart(int mid, int k); intbsearchStart(int q[], int l, int r, int k); boolcheckEnd(int mid, int k); intbsearchEnd(int q[], int l, int r, int k); intmain(void) { int m; // m表示询问次数 scanf("%d %d", &n, &m); // 差点忘记给n和m加上引用符号 for (int i = 0; i < n; i++) scanf("%d", &q[i]); int k; // 要查询的元素 while (m--) { scanf("%d", &k); int startIndex = bsearchStart(q, 0, n - 1, k); int startEnd = bsearchEnd(q, 0, n - 1, k); cout << startIndex << " " << startEnd << endl; }
return0; }
boolcheckEnd(int mid, int k) { if (q[mid] <= k) returntrue; // 红色分界点就是从右往左第一个小于等于k的数字,就是题干要我们找的答案之二,就是数字k的结束位置 else returnfalse; } boolcheckStart(int mid, int k) { if (q[mid] >= k) returntrue; // 绿色分界点就是第一个大于等于k的数字,就是题干要我们找的答案之一,就是数字k的开始位置 else returnfalse; } intbsearchStart(int q[], int l, int r, int k) {
while (l < r) { // 应该是l < r不带等号,因为要保证循环结束的时候l == r从而区间里面只有一个数,这个数就是我们要找的答案,就是红绿区间分界点 int mid = l + r >> 1; // mid应该在while里面,不然每一次循环mid都一直是最开始的l和最开始的r的和的一半 if (checkStart(mid, k)) r = mid; // 既然是r = mid就不用让mid = l + r + 1 >> 1 else l = mid + 1; } if (q[l] != k) // 这是因为题干要求而在模板基础上做的改变. return-1; // 如果q[l] != k,说明这个数字q[]里面没有数值等于k 的数字,不存在该元素,就返回 -1 else return l; } intbsearchEnd(int q[], int l, int r, int k) {
while (l < r) { // 应该是l < r不带等号,因为要保证循环结束的时候l == r从而区间里面只有一个数,这个数就是我们要找的答案,就是红绿区间分界点 int mid = l + r + 1 >> 1; // mid应该在while里面,不然每一次循环mid都一直是最开始的l和最开始的r的和的一半 if (checkEnd(mid, k)) l = mid; // 既然是l = mid就必要让mid = l + r + 1 >> 1 else r = mid - 1; } if (q[l] != k) // 这是因为题干要求而在模板基础上做的改变. return-1; // 如果q[l] != k,说明这个数字q[]里面没有数值等于k 的数字,不存在该元素,就返回 -1 else return l; }
写的时候的疑点:
第一个疑点
int q[N]; // 记录自己每一次不太确定的部分,好像是N,不是n
这里就是N,N表示数组的最大空间是MAX
n是你输入的元素个数,是size
第二个疑点
int bsearchStart(int q[], int l, int r, int k);和int bsearchEnd(int q[], int l, int r, int k);不用传数组int q[]因为你已经把他定义成全局变量了.只用传入数组的开始下标0,数组的结束下标n - 1,要查询的数字k
#include<iostream> usingnamespace std; constint N = 100010; int n; int q[N]; boolcheckStart(int mid, int k); boolcheckEnd(int mid, int k); intbsearchStart(int l, int r, int k); intbsearchEnd(int l, int r, int k); intmain(void) { int m;
cin >> n >> m; for (int i = 0; i < n; i++) scanf("%d", &q[i]);
while (m--) { int k; cin >> k; int indexStart = bsearchStart(0, n - 1, k); int indexEnd = bsearchEnd(0, n - 1, k); cout << indexStart << " " << indexEnd << endl; } return0; } boolcheckStart(int mid, int k) { if (q[mid] >= k) returntrue; else returnfalse; } boolcheckEnd(int mid, int k) { if (q[mid] <= k) returntrue; else returnfalse; } intbsearchStart(int l, int r, int k) { while (l < r) { int mid = l + r >> 1; if (checkStart(mid, k)) r = mid; else l = mid + 1; } if (q[l] != k) return-1; else return l; } intbsearchEnd(int l, int r, int k) { while (l < r) { int mid = l + r + 1 >> 1; if (checkEnd(mid, k)) l = mid; else r = mid - 1; } if (q[l] != k) return-1; else return l; }
constint N = 100010; vector<int> add(vector<int> &A, vector<int> &B); intmain(void) { string a, b; cin >> a >> b; vector<int> A, B; for (int i = a.size() - 1; i >= 0; i--) { A.push_back(a[i] - '0'); } for (int i = b.size() - 1; i >= 0; i--) { B.push_back(b[i] - '0'); } vector<int> C = add(A, B); for (int i = C.size() - 1; i >= 0; i--) { printf("%d", C[i]); } return0; } vector<int> add(vector<int> &A, vector<int> &B) { vector<int> C; int t = 0; for (int i = 0; i < A.size() || i < B.size(); i++) { if (i < A.size()) t += A[i]; if (i < B.size()) t += B[i]; C.push_back(t % 10); t /= 10; } if (t) C.push_back(1); return C; }
constint N = 100010; vector<int> mul(vector<int> &A, int b); intmain(void) { string a; int b; cin >> a >> b; vector<int> A; for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
auto C = mul(A, b); for (int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]); return0; } vector<int> mul(vector<int> &A, int b) { // 先尝试自己写 vector<int> C; int t = 0; // 这里i < A.size() || t你用我之前的true和false分别分四种情况看一看就能理解了 for (int i = 0; i < A.size() || t; i++) { if (i < A.size()) t += A[i] * b; C.push_back(t % 10); t /= 10; }
constint N = 1010; int n, m, q; int a[N][N], b[N][N]; voidinsert(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; } intmain(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, 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++) b[i][j] = b[i][j] + b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) printf("%d ", b[i][j]); printf("\n"); } return0; }