//核心思想:分而治之
//函数参数:(需要处理的数组, 数组的左边界, 数组的右边界)
//函数:使得左边小于x, 右边大于x
void quick_sort(int q[], int l, int r)
{
//递归出口
if (l >= r) return;
//运用双指针,左指针指向的数小于x, 右指针指向的数大于x
int x = (q[l] + q[r]) / 2;
int 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);
}
1.分成子问题:将数组分为左边小于x, 右边大于x
2.递归处理子问题:递归处理左右子区间
3.子问题合并
#include
#include
using namespace std;
const int N = 100010;
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int x = (q[l] + q[r]) / 2;
int 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);
}
int main()
{
int n;
int q[N];
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]);
}
#include
#include
using namespace std;
const int N = 100010;
void quick_sort(int q[], int l, int r)
{
if (l >= r) return ;
int x = (q[l] + q[r]) / 2;
int 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);
}
int main()
{
int q[N];
int n, k;
scanf ("%d %d", &n, &k);
for (int i = 0; i < n; i ++ )
scanf("%d", &q[i]);
quick_sort(q, 0, n - 1);
printf("%d\n", q[k - 1]);
}
//核心思想:分而治之
//函数参数:(需要处理的数组, 数组左边界, 数组右边界)
//函数:使得以mid下标两侧的区间有序
void merge_sort(int q[], int l, int r)
{
//递归出口
if (l >= r) return ;
//分成左右子区间:使得左右两个区间有序
int mid = (l + r) / 2;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
//合并左右子区间
int i = l;
int j = mid + 1;
int k = 0;
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 = 0, j = l; i < k; i ++, j ++) q[j] = tmp[i];
}
1.分成子问题:以mid为分界线的左右区间有序
2.递归处理子问题:递归处理左右子区间
3.子问题合并:将左右区间有序数组合并
#include
#include
using namespace std;
const int N = 100010;
int tmp[N];
void merge_sort(int q[], int l, int r)
{
//递归出口
if (l >= r) return ;
//分成子问题
int mid = (l + r) / 2;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
//合并
int i = l;
int j = mid + 1;
int k = 0;
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 = 0, j = l; i < k; i ++, j ++) q[j] = tmp[i];
}
int main()
{
int q[N];
int n;
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]);
}
解析:
#include
#include
using namespace std;
const int N = 100010;
typedef long long LL;
int q[N], tmp[N];
LL len;
void merge_sort(int q[], int l, int r)
{
if (l >= r) return ;
int mid = (l + r) / 2;
merge_sort (q, l, mid);
merge_sort (q, mid + 1, r);
int i = l;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= r)
{
if (q[i] <= q[j]) tmp[k ++] = q[i ++];
else
{
tmp[k ++] = q[j ++];
len += mid - i + 1;
}
}
while (i <= mid) tmp[k ++] = q[i ++];
while (j <= r) tmp[k ++] = q[j ++];
for (int i = 0, j = l; i < k; i ++, j ++ ) q[j] = tmp[i];
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
merge_sort(q, 0, n - 1);
printf("%lld\n", len);
}
int l = 0;
int r = n - 1;
while (l < r)
{
int mid = (l + r) / 2;
if (a[mid] >= x) r = mid;
else l = mid + 1;
}
l = 0;
r = n - 1;
while(l < r)
{
int mid = (l + r + 1) / 2;
if (a[mid] <= x) l = mid;
else r = mid - 1;
}
根据a[mid]与x的大小关系,不断更新左右区间
#include
#include
using namespace std;
const int N = 100010;
int main()
{
int n, q;
scanf("%d%d", &n, &q);
int a[N];
for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
while (q --)
{
int x;
scanf("%d", &x);
int l = 0;
int r = n - 1;
while (l < r)
{
int mid = (l + r) / 2;
if (a[mid] >= x) r = mid;
else l = mid + 1;
}
if (a[l] != x) printf("%d %d\n", -1, -1);
else
{
printf("%d ", l);
l = 0;
r = n - 1;
while(l < r)
{
int mid = (l + r + 1) / 2;
if (a[mid] <= x) l = mid;
else r = mid - 1;
}
printf("%d\n", r);
}
}
}
#include
#include
using namespace std;
int main()
{
double x;
scanf("%lf", &x);
double l = -10000;
double r = 10000;
while (r - l >= 1e-8)
{
double mid = (l + r) / 2;
if (mid * mid * mid >= x) r = mid;
else l = mid;
}
printf("%.6lf\n", l);
}
1.将数字当成字符串读入
2.字符串转换成数组(从低位向高位)
3.数组每个数字相加(注意有进位)
vector add(vector x, vector y)
{
vector res; //存储加法结果
if (x.size() < y.size()) return add(y, x);
int t = 0;
for (int i = 0; i < x.size(); i ++ )
{
t += x[i];
if (i < y.size()) t += y[i];
res.push_back(t % 10);
t /= 10;
}
if (t) res.push_back(t);
return res;
}
#include
#include
#include
#include
using namespace std;
vector add(vector x, vector y)
{
vector res; //存储加法结果
if (x.size() < y.size()) return add(y, x);
int t = 0;
for (int i = 0; i < x.size(); i ++ )
{
t += x[i];
if (i < y.size()) t += y[i];
res.push_back(t % 10);
t /= 10;
}
if (t) res.push_back(t);
return res;
}
int main()
{
vector x, y;
string a, b;
cin >> a >> b;
for (int i = a.size() - 1; i >= 0; i -- ) x.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i -- ) y.push_back(b[i] - '0');
vector res = add(x, y);
for (int i = res.size() - 1; i >= 0; i -- ) cout << res[i];
}
1.将数字按照字符串读入
2.字符串转化为数组
3.比较两个数字大小
4.两个数字相减,大数减小数
5.去掉前导0
//比较x与y的大小
// x >= y 返回true
bool cmp(vector x, vector y)
{
if (x.size() != y.size()) return x.size() > y.size();
for (int i = x.size() - 1; i >= 0; i -- )
if (x[i] != y[i]) return x[i] > y[i];
return true;
}
vector sub(vector x, vector y)
{
vector res;
int t = 0;
for (int i = 0; i < x.size(); i ++ )
{
t = x[i] - t;
if (i < y.size()) t -= y[i];
res.push_back((t + 10) % 10);
if (t < 0) t = 1;
else t = 0;
}
//前缀0去掉
while (res.size() > 1 && res.back() == 0) res.pop_back();
return res;
}
#include
#include
#include
#include
using namespace std;
//比较x与y的大小
// x >= y 返回true
bool cmp(vector x, vector y)
{
if (x.size() != y.size()) return x.size() > y.size();
for (int i = x.size() - 1; i >= 0; i -- )
if (x[i] != y[i]) return x[i] > y[i];
return true;
}
vector sub(vector x, vector y)
{
vector res;
int t = 0;
for (int i = 0; i < x.size(); i ++ )
{
t = x[i] - t;
if (i < y.size()) t -= y[i];
res.push_back((t + 10) % 10);
if (t < 0) t = 1;
else t = 0;
}
//前缀0去掉
while (res.size() > 1 && res.back() == 0) res.pop_back();
return res;
}
int main()
{
string a, b;
cin >> a >> b;
vector x, y;
for (int i = a.size() - 1; i >= 0; i -- ) x.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i -- ) y.push_back(b[i] - '0');
vector res;
if (cmp(x, y)) res = sub(x, y);
else
{
cout << '-';
res = sub(y, x);
}
for (int i = res.size() - 1; i >= 0; i -- )
cout << res[i];
return 0;
}
1.规模大的数字按照字符串读入
2.将字符串转化为数组
3.将数组中的每一个数与数字相乘
vector mul(vector x, int y)
{
vector res;
int t = 0;
for (int i = 0; i < x.size(); i ++ )
{
t += x[i] * y;
res.push_back(t % 10);
t /= 10;
}
while (t)
{
res.push_back(t % 10);
t /= 10;
}
return res;
}
#include
#include
#include
#include
using namespace std;
vector mul(vector x, int y)
{
vector res;
int t = 0;
for (int i = 0; i < x.size(); i ++ )
{
t += x[i] * y;
res.push_back(t % 10);
t /= 10;
}
while (t)
{
res.push_back(t % 10);
t /= 10;
}
return res;
}
int main()
{
string a;
int b;
cin >> a >> b;
if (b == 0)
{
cout << '0';
return 0;
}
vector x;
for (int i = a.size() - 1; i >= 0; i -- ) x.push_back(a[i] - '0');
vector res = mul(x, b);
for (int i = res.size() - 1; i >= 0; i -- ) cout << res[i];
return 0;
}
1.规模大的数字按照字符串读入
2.将字符串转化为数组
3.将数组中的每一个数与数字相除
4.去除前导0
int t;
vector divide(vector x, int b)
{
vector res;
for (int i = 0; i < x.size(); i ++ )
{
t = t * 10 + x[i];
res.push_back(t / b);
t = t % b;
}
reverse(res.begin(), res.end());
while (res.size() > 1 && res.back() == 0) res.pop_back();
return res;
}
#include
#include
#include
#include
using namespace std;
int t;
vector divide(vector x, int b)
{
vector res;
for (int i = 0; i < x.size(); i ++ )
{
t = t * 10 + x[i];
res.push_back(t / b);
t = t % b;
}
reverse(res.begin(), res.end());
while (res.size() > 1 && res.back() == 0) res.pop_back();
return res;
}
int main()
{
string a;
int b;
cin >> a >> b;
vector x;
for (int i = a.size() - 1; i >= 0; i -- ) x.push_back(a[i] - '0');
reverse(x.begin(), x.end());
vector res = divide(x, b);
for (int i = res.size() - 1; i >= 0; i -- ) cout << res[i];
cout << endl;
cout << t << endl;
}
int n, m;
int sum[N];
void Prefix_and(int a[])
{
for (int i = 1; i <= n; i ++ ) sum[i] = sum[i - 1] + a[i];
}
int Sum(int l, int r)
{
return sum[r] - sum[l - 1];
}
#include
using namespace std;
const int N = 100010;
int n, m;
int sum[N];
void Prefix_and(int a[])
{
for (int i = 1; i <= n; i ++ ) sum[i] = sum[i - 1] + a[i];
}
int Sum(int l, int r)
{
return sum[r] - sum[l - 1];
}
int main()
{
cin >> n >> m;
int a[N];
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
Prefix_and(a);
while (m --)
{
int l, r;
cin >> l >> r;
cout << Sum(l, r) << endl;;
}
}
int n, m;
int sum[N][N];
void Prefix_and(int a[N][N])
{
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
}
int Sum(int x1, int y1, int x2, int y2)
{
int res = sum[x2][y2] - sum[x2][y1 - 1] - sum[x1 - 1][y2] + sum[x1 - 1][y1 - 1];
return res;
}
#include
using namespace std;
const int N = 1010;
int n, m;
int sum[N][N];
void Prefix_and(int a[N][N])
{
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
}
int Sum(int x1, int y1, int x2, int y2)
{
int res = sum[x2][y2] - sum[x2][y1 - 1] - sum[x1 - 1][y2] + sum[x1 - 1][y1 - 1];
return res;
}
int main()
{
int q;
cin >> n >> m >> q;
int a[N][N];
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
cin >> a[i][j];
Prefix_and(a);
while (q --)
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
cout << Sum(x1, y1, x2, y2) << endl;
}
}
对于差分数组b,可以看作b求前缀和就等于a
对于给定区间[l, r], 每一个数都加上c:
b[l] + c 可以使得 a[l ~ n]的每一个数都加上c
b[r + 1] - c 可以使得 a[r + 1 ~ n] 的每一个数都减上c
void insert(int l, int r, int c)
{
b[l] += c;
b[r + 1] -= c;
}
#include
using namespace std;
const int N = 100010;
int a[N], b[N];
void insert(int l, int r, int c)
{
b[l] += c;
b[r + 1] -= c;
}
int main()
{
int n, m;
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 ++ )
{
b[i] += b[i - 1];
cout << b[i] << ' ';
}
}
int a[N][N], b[N][N];
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;
}
#include
using namespace std;
const int N = 1010;
int a[N][N], b[N][N];
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()
{
int n, m, q;
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]);
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 - 1][j] + b[i][j - 1] - b[i - 1][j - 1] + b[i][j];
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= m; j ++ )
{
printf("%d ", b[i][j]);
}
puts("");
}
}
双指针是一种思想,没有具体模板
#include
#include
#include
using namespace std;
const int N = 1e5 + 10;
int s[N];
int main()
{
int n;
scanf("%d", &n);
int a[N];
for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
int res = 0;
int j = 0;
for (int i = 0; i < n; i ++ )
{
s[a[i]] ++;
while (s[a[i]] > 1)
{
s[a[j]] --;
j ++;
}
res = max(res, i - j + 1);
}
cout << res << endl;
}
#include
#include
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
int main()
{
int n, m, x;
cin >> n >> m >> x;
LL a[N], b[N];
for (int i = 0; i < n; i ++ ) cin >> a[i];
for (int i = 0; i < m; i ++ ) cin >> b[i];
int j = m - 1;
for (int i = 0; i < n; i ++ )
{
while (j >= 0 && a[i] + b[j] > x) j --;
if (a[i] + b[j] == x) cout << i << ' ' << j << endl;
}
}
#include
using namespace std;
const int N = 1e5 + 10;
int main()
{
int n, m;
cin >> n >> m;
int a[N], b[N];
for (int i = 0; i < n; i ++ ) cin >> a[i];
for (int i = 0; i < m; i ++ ) cin >> b[i];
int i = 0, j = 0;
while (i < n && j < m)
{
if (a[i] == b[j]) i ++;
j ++;
}
if (i == n) puts("Yes");
else puts("No");
}
x >> k & 1;
lowbit(x) = x & -x;
#include
using namespace std;
int lowbit(int x)
{
return x & -x;
}
int main()
{
int n;
cin >> n;
while (n --)
{
int x;
cin >> x;
int cnt = 0;
while (x)
{
x -= lowbit(x);
cnt ++;
}
cout << cnt << ' ';
}
}
值域大,个数少。
1.用可变数组存储所有的下标,按大小排序后去重
2.用二分查找的方法,查找出离散后的坐标,构造离散化以后的数组
sort(alls.begin(), alls.end());
alls.erase(unique(alls.begin(), alls.end()), alls.end());
vector alls;
int find(int x)
{
int l = 0, r = alls.size();
while (l < r)
{
int mid = (l + r) / 2;
if (alls[mid] >= x) r = mid;
else l = mid + 1;
}
return l + 1;
}
#include
#include
#include
using namespace std;
const int N = 300010;
typedef pair PII;
int n, m;
int a[N], s[N];
vector alls;
vector add, query;
int find(int x)
{
int l = 0, r = alls.size();
while (l < r)
{
int mid = (l + r) / 2;
if (alls[mid] >= x) r = mid;
else l = mid + 1;
}
return l + 1;
}
int main()
{
cin >> n >> m;
while (n --)
{
int x, c;
cin >> x >> c;
alls.push_back(x);
add.push_back({x, c});
}
while (m --)
{
int l, r;
cin >> l >> r;
alls.push_back(l);
alls.push_back(r);
query.push_back({l, r});
}
//去重
sort(alls.begin(), alls.end());
alls.erase(unique(alls.begin(), alls.end()), alls.end());
for(auto item: add)
{
int k = find(item.first);
a[k] = item.second;
}
for (int i = 1; i <= alls.size(); i ++ ) s[i] = s[i - 1] + a[i];
for(auto item: query)
{
int l = find(item.first), r = find(item.second);
cout << s[r] - s[l - 1] << endl;
}
}
vector segs, res;
void merge(vector segs)
{
sort(segs.begin(), segs.end());
int st = -2e9, ed = -2e9;
for(auto item : segs)
{
if (ed < item.first)
{
if (ed != -2e9) res.push_back({st, ed});
st = item.first;
ed = item.second;
}
else ed = max(ed, item.second);
}
if (st != -2e9) res.push_back({st, ed});
}
#include
#include
#include
using namespace std;
typedef pair PII;
vector segs, res;
void merge(vector segs)
{
sort(segs.begin(), segs.end());
int st = -2e9, ed = -2e9;
for(auto item : segs)
{
if (ed < item.first)
{
if (ed != -2e9) res.push_back({st, ed});
st = item.first;
ed = item.second;
}
else ed = max(ed, item.second);
}
if (st != -2e9) res.push_back({st, ed});
}
int main()
{
int n;
cin >> n;
while (n --)
{
int l, r;
cin >> l >> r;
segs.push_back({l, r});
}
merge(segs);
cout << res.size() << endl;
}
如有错误,欢迎指正!!!