一维差分、二维差分模板

目录

一维差分

二维差分

补充练习题


一维差分

参考资料:

【C++】一维、二维差分+模板+例题_c语言差分练习题-CSDN博客

模板题目:

https://www.luogu.com.cn/problem/P2367

模板代码:

#include <stdint.h>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <thread>
#include <iostream>

using namespace std;

const int maxn = 5e6+5;
int a[maxn];
int diff[maxn];

void insert(int l, int r, int c)
{
    diff[l] += c;
    diff[r+1] -= c;
}

int main() {
    int n,p;
    cin >> n >> p;
    for(int i=1;i<=n;++i)
    {
        cin >> a[i];
    }

    a[0]=0;
    for(int i=1;i<=n;++i)
    {
        diff[i] = a[i] - a[i-1];
    }

    int l,r,c;
    while(p--)
    {
        cin >> l >> r >> c;
        insert(l, r, c);
    }
    int ans = maxn, sum =0;
    for(int i=1;i<=n;++i)
    {
        sum+=diff[i];
        ans = min(ans, sum);
    }
    cout << ans <<endl;
    // system("pause");
    return 0;
}

二维差分

参考资料:

算法基础(五)| 差分算法及模板详解-腾讯云开发者社区-腾讯云

差分——(2)二维差分_二维差分非矩形-CSDN博客

算法笔记(六):差分法_差分算法-CSDN博客

模板题目:

https://www.luogu.com.cn/problem/P5542

模板代码:

#include <stdint.h>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <thread>
#include <iostream>

using namespace std;

const int maxn = 1005;
int a[maxn][maxn];    // 以下坐标起始点都为(1,1)
int diff[maxn][maxn]; // 表示从(1,1)到(i,j)的差分矩阵
int ans[maxn][maxn];  // 最终结果矩阵

void init()
{
    memset(a, 0, sizeof(a));
    memset(diff, 0, sizeof(diff));
    memset(ans, 0, sizeof(ans));
}

void build_diff_array(int n, int m)
{
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= m; ++j)
        {
            diff[i][j] = a[i][j] - a[i - 1][j] - a[i][j - 1] + a[i - 1][j - 1];
        }
    }
    return;
}

void region_add(int x1, int y1, int x2, int y2, int val) // 左上角和右下角
{
    diff[x1][y1] += val;
    diff[x1][y2 + 1] -= val;
    diff[x2 + 1][y1] -= val;
    diff[x2 + 1][y2 + 1] += val;
}

void build_ans_array(int n, int m)
{
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= m; ++j)
        {
            ans[i][j] = diff[i][j] + ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1];
        }
    }
    return;
}

int main()
{
    int n, k, x1, y1, x2, y2;
    scanf("%d%d", &n, &k);
    init();
    while (n--)
    {
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        region_add(x1+1, y1+1, x2, y2, 1);  // 这里注意坐标位置
    }

    build_ans_array(1000, 1000);
    int sum = 0;
    for (int i = 1; i <= 1000; ++i)
    {
        for (int j = 1; j <= 1000; ++j)
        {
            if (ans[i][j] == k)
                sum++;
        }
    }
    printf("%d\n", sum);

    return 0;
}

补充练习题

https://codeforces.com/contest/2000/problem/E

ac代码:

#include <stdint.h>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <thread>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;

const int maxn = 2e5 + 5;
/*int a[maxn][maxn];    // 以下坐标起始点都为(1,1)
int diff[maxn][maxn]; // 表示从(1,1)到(i,j)的差分矩阵
int ans[maxn][maxn];  // 最终结果矩阵
int h[maxn];*/
/*void init()
{
    memset(a, 0, sizeof(a));
    memset(diff, 0, sizeof(diff));
    memset(ans, 0, sizeof(ans));
}

void build_diff_array(int n, int m)
{
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= m; ++j)
        {
            diff[i][j] = a[i][j] - a[i - 1][j] - a[i][j - 1] + a[i - 1][j - 1];
        }
    }
    return;
}*/

void region_add(int x1, int y1, int x2, int y2, int val, vector<vector<int>> &diff) // 左上角和右下角
{
    diff[x1][y1] += val;
    diff[x1][y2 + 1] -= val;
    diff[x2 + 1][y1] -= val;
    diff[x2 + 1][y2 + 1] += val;
}

void build_ans_array(int n, int m, vector<vector<int>> &diff, vector<vector<int>> &ans)
{
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= m; ++j)
        {
            ans[i][j] = diff[i][j] + ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1];
        }
    }
    return;
}

void slove()
{
    int n, m, k, w;
    scanf("%d%d%d", &n, &m, &k);

    vector<vector<int>> diff(n + 5, vector<int>(m + 5, 0));
    vector<vector<int>> ans(n + 5, vector<int>(m + 5, 0));

    scanf("%d", &w);

    vector<int> h(w + 5, 0);
    for (int i = 0; i < w; ++i)
    {
        scanf("%d", &h[i]);
    }
    sort(h.begin(), h.begin() + w, greater<int>());

    for (int i = 1; i <= n - k + 1; ++i)
    {
        for (int j = 1; j <= m - k + 1; ++j)
        {
            region_add(i, j, i + k - 1, j + k - 1, 1, diff);
        }
    }
    build_ans_array(n, m, diff, ans);

    vector<int> vec;
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= m; ++j)
        {
            vec.push_back(ans[i][j]);
            // printf("%d ", ans[i][j]);
            // if(j==m)
            //     printf("\n");
        }
    }
    sort(vec.begin(), vec.end(), greater<int>());

    ll sum = 0;
    for (int i = 0; i < w; ++i)
    {
        // printf("i=%d %d %d\n",i, vec[i],h[i]);
        sum += (ll)vec[i] * h[i];
    }
    printf("%lld\n", sum);
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        slove();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值