AcWing 787. 归并排序
一,知识概况:
1.并归思维。
二,代码示例:
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N], tmp[N];
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
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 (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
merge_sort(a, 0, n - 1);
for (int i = 0; i < n; i ++ ) printf("%d ", a[i]);
return 0;
}
作者:yxc
链接:https://www.acwing.com/activity/content/code/content/39790/
来源:AcWing
三,理解思路:
一,并归思维:
想要并和归,自然要先分,把一个问题分成两个小分,依次分下去,但变成一个一个时,就可以开始判断且合并了(并),判断的结果返回回去和大一级的小分继续刚才的操作(归),直至输出结果。
使用条件:
1.可以进行分开判断,且判断条件简单。
2.判断数据需要总和,(归并思维是在于并,并的时候的判断大概率是来解决问题的。)
使用步骤:
1.定义中点。
2.进行分与并。(在归并排序中,分是把一串数据层层分组,到最后只有一个一个的数,无法对比进行返回,返回一组进行一次判断,返回上一层的数组判断,最终达到排序的效果。并则是里面的进行判断时进行的两组排序。)
3.找到都可以使用的判断条件。
临时模板:
int mid = l + r >> 1;
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 (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
四,结语:
要注意用计算机思维看问题,并归思维其实很简单,因为只看代码,没看见代码下面的计算很容易迷糊。
acwing 789. 数的范围
一,知识概括:
1.二分思维。
二,代码示例:
#include <iostream>
using namespace std;
const int N = 100010;
int n, m;
int q[N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
while (m -- )
{
int x;
scanf("%d", &x);
int l = 0, r = n - 1;
while (l < r)
{
int mid = l + r >> 1;
if (q[mid] >= x) r = mid;
else l = mid + 1;
}
if (q[l] != x) cout << "-1 -1" << endl;
else
{
cout << l << ' ';
int l = 0, r = n - 1;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (q[mid] <= x) l = mid;
else r = mid - 1;
}
cout << l << endl;
}
}
return 0;
}
作者:yxc
链接:https://www.acwing.com/activity/content/code/content/39787/
来源:AcWing
三,思维理解:
一,二分思维:
yxc在说过二分的本质是边界,是通过判断mid与需要判断的值的关系,改变左右边界,要到达不断收缩区间进行判断,找到目标值。(比如数字4,可以确定精度。)
使用则要注意题目:
1.可以通过一简单的判断找到目标值。
2.整个数据是具体的数据,可以进行缩减的。
3.目标值是可以确认的。
使用步骤:
1.确定mid值,
2.找到缩小区间的判断条件。
3.找到确认目标值的判断条件。
yxc的模板:
while (l < r)
{
int mid = l + r + 1 >> 1;
if (q[mid] <= x) l = mid;
else r = mid - 1;
}/* - 1就要 + 1。(注意:不加1,在只有一个数时,
mid会跑出范围,得到两个数据进行判断,则循环无法结束。)*/
while (l < r)
{
int mid = l + r >> 1;
if (q[mid] >= x) r = mid;
else l = mid + 1;
}//无需+ 1。
while (r - l > 1e-8)//精度需求。
{
double mid = (l + r) / 2;
if (mid * mid * mid >= x) r = mid;//本题是求根号3。
else l = mid;
}
四,结语:
多练。
————这是鄙人没有什么学识,如有错误,请尽情留言。