关于去写没动过的AcWings寒假题的以外收获——差分

给我去看高木啊!!!!


前言

久违地写一篇博客,没想到世界上还有差分这么好的东宫西,看来我还是太水了。


提示:以下是本篇文章正文内容,下面案例可供参考

一、差分是什么?

差分就是给定你一个数列,然后第i项减去第i-1项,这样得到的数列称为差分数列。

二、原理述说

     1.对差分数列求前缀和可得原数列;
     2.当对原数列区间[l,r]加x时,等价于对其差分数列第l项+x,第r+1项-x

性质1就不解释了,这里说下性质2
我们考虑这样一个数列 1 2 3 4 5 6 7;
其差分数列为:            1 1 1 1 1 1 1

我令其原数列第3-5项+1有:
                                     1 2 4 5 6 6 7
其差分数列为:            1 1 2 1 1 0 1

发现了吗?
                                     1 1 1 1 1 1 1
                                             👇
                                     1 1 2 1 1 0 1
                                             👇
                                     1 2 4 5 6 6 7

这是为什么呢?
这是因为当第[l,r]项+x时第l项与第l-1项的差值+x,第[l,r]项差值未变,第r+1项与第r项的差值+x,所以,对原数列[l,r]项+x等价于对其差分数列第l项+x,第r+1项-x。


例子

这里以AcWings寒假2022-2041.干草堆为例
2041.干草堆
不会导题进来,自己点开看题再看我这里。、

这里就是最基础的差分法使用

#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <iomanip>
#include <bits/stdc++.h>
using namespace std;

int a[10000000], b[10000000];
int spent[100000], good[100000];
int height[10000000];
string str[11];

bool cmp(int a, int b)
{
    return a > b;
}


int main()
{
    int n, k;
    cin >> n >> k;
    int l, r;
    memset(height, 0, sizeof(height));
    //直接构造差分数列,这里直接应用了性质1
    for (int i = 0; i < k; i++)
    {
        cin >> l >> r;//注意,我这里的数组是从0开始的所以是l-1和r
        //建议不要学我,都从1开始,我是习惯了这么开数组。当然也吃了很多亏
        height[l-1]++;//第l项+x,这里的x=1;
        height[r]--;//第r+1项-x
    }

    for (int i = 1; i < n; i++)
    {
        height[i] += height[i - 1];//再次利用性质1,获得原数列
    }
    sort(height, height + n);//排序
    
    //输出中值高度
    cout<< height[n / 2];

    return 0;
}

总结

春季2022做了,结果今天还没更新,没题做了就打开了没动过的寒假题,实在是太好了,学到了差分!

这个差分是可以减少无用的加减法的!
这里贴个我这道题最初的代码,直接超时:
愿意的话你们可以去试一试

#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <iomanip>
#include <bits/stdc++.h>
using namespace std;

int a[10000000], b[10000000];
int spent[100000], good[100000];
int height[10000000];
string str[11];

bool cmp(int a, int b)
{
    return a > b;
}


int main()
{
    int n, k;
    cin >> n >> k;
    memset(height, 0, sizeof(height));
    for (int i = 0; i < k; i++)
    {
        cin >> a[i] >> b[i];
        for (int j = a[i]; j <= b[i]; j++)
        {
            height[j]++;
        }
    }
    sort(height, height + n);
    cout << height[(n - 1) / 2];
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值