设为首页 加入收藏

TOP

C++算法之旅、04 基础篇 | 第一章 基础算法(四)
2023-09-09 10:25:47 】 浏览:206
Tags:
hile (q--) { int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; int res = S[x2][y2] - S[x1 - 1][y2] - S[x2][y1 - 1] + S[x1 - 1][y1 - 1]; cout << res << endl; } return 0; }

一维差分

b为a的差分,a为b的前缀和。\(b_1 = a_1\) , \(b_n = a_n - a_{n-1}\)

前缀和转差分

假想前缀和全为0,此时差分全为0。然后模拟插入,即前缀和 [1,1] 元素加上 \(a_1\),[2,2] 元素加上 \(a_2\),[n,n] 元素加上 \(a_n\)

797

797. 差分 - AcWing题库

image-20230901023819859

由 b 数组(差分)得到 a 数组(前缀和)O(n)

给 [L,R] 每个数加上 c,每次操作暴力方法 O(n),使用差分 O(1)

#include <cstdio>
#include <iostream>

using namespace std;

const int N = 1e6 + 10;

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++) {
        scanf("%d", &a[i]);
    }
    // 前缀和转差分
    for (int i = 1; i <= n; i++) {
        insert(i, i, a[i]);
    }
    int l, r, c;
    while (m--) {
        scanf("%d%d%d", &l, &r, &c);
        insert(l, r, c);
    }
    // 差分转前缀和
    for (int i = 1; i <= n; i++) b[i] += b[i - 1];
    for (int i = 1; i <= n; i++) cout << b[i] << " ";
    return 0;
}

二维差分

构造 \(b_{ij}\) 满足 \(a_{ij} = \sum_{1}^{n}\sum_{1}^{m}b_{ij}\)

子矩阵全加c

\(b_{x_1,y_1} += c \\ b_{x_{2}+1,y_1} -= c \\ b_{x_1,y_{2}+1} -=c \\b_{x_{2} + 1,y_{2} +1} += c\)

前缀和转差分

假想前缀和全为0,此时差分全为0。然后模拟插入,即模拟子矩阵 [1 , 1][1 , 1] 加 c


798

798. 差分矩阵 - AcWing题库

#include <cstdio>
#include <iostream>

using namespace std;

const int N = 1e3 + 10;

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;
    cin >> 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;
        cin >> 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++) cout << b[i][j] << " ";
        cout << endl;
    }

    return 0;
}

双指针算法

用于把朴素算法优化到 O(n)

for (int i = 0, j = 0; i < n; i ++ )
{
    while (j < i && check(i, j)) j ++ ;

    // 具体问题的逻辑
}

第一类双指针

指向两个序列,用两个指针维护一段区间

第二类双指针

指向一个序列,如快排。维护某种次序,比如归并排序中合并两个有序序列的操作


799 ?? 第一类

799. 最长连续不重复子序列 - AcWing题库

数据量 1e5 ,用数组统计出现次数。当数据量很大时用哈希表做

从朴素算法看 i,j 的单调关系,然后套用双指针。两个指针 [i,j] 维护一个最长不重复序列区间。i,j 一定是往右走的(单调性),若 i 往左走则与最长不重复序列区间矛盾。

#include <algorithm>
#include <cstdio>
#include <iostream>

using namespace std;

const int N = 1e5 + 10;

int a[N], b[N];

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    int count = 0;
    for (int i = 0, j = 0; j < n; j++) {
        b[a[j]]++;
        while (b[a[j]] > 1) {
            b[a[i]]--;
            i++;
        }
        count = max(j - i + 1, count);
    }
    cout << count;
    return 0;
}

800 第二类

800. 数组元素的目标和 - AcWing题库

#include <algorithm>
#include <cstdio>
#include <iostream>

using namespace std;

const int N = 1e6 + 10;

int a[N], b[N];

int main() {
    int n, m, x;
    cin >> n >> m >> x;
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    for (int i = 0; i < m; i++) {
        scanf("%d", &b[i]);
    }
    for (int i = 0, j = m - 1; i < n && a[i] < x; i++) {
        while (j >= 0 && b[j] > x - a[i]) j--;
        if (a[i
首页 上一页 1 2 3 4 5 6 下一页 尾页 4/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇1.12 进程注入ShellCode套接字 下一篇[Qt开发探幽(二)]浅谈关于元对..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目