简单差分

简单差分

可能这里的阅读体验更好:https://www.zybuluo.com/Junlier/note/1232395

引入

首先,给出一个问题:
给出n个数,再给出Q个询问,每个询问给出le,ri,x,要求你在le到ri上每一个值都加上x,而只给你O(n)的时间范围,怎么办?
思考一下:

如果暴力,卡一下le和ri,随随便便让你O(n^2)T成狗。
用线段树或树状数组搞一搞,抱歉,这个复杂度是O(Qlogn)的,还是会T(虽然他们解决别的题目很NB)
差分,没错,就是标题,很高兴O(n)+常数…
方法

还是用上面这个题目,假如要在le和ri上全都加一个x,很显然,这个O(n)是不可避免的,既然这样,那我们考虑把O(n*Q)变成O(n+Q).也就是说,在询问中我们不去for来加x,而是做一个标记,最后一起加上。嗯,这里暂时记住就好…
现在需要自己动笔模拟一下了!

实现

先另外开一个专门差分的数组(大小=题中的序列长度)

假如在3~8的区间上加上5,那我们在差分数组中的3位置上加上一个5(原因暂时不懂没关系,用笔先跟着模拟),再在8+1的位置上减一个5,如此操作完Q次。

假如我们只有这一次操作,开始统计答案,运用前置和的思想,cfi=cf[i-1]+cf[i].那么你会发现(如果你模拟了的话),在3~8的区间上,你已经使差分数组全部加上了5(推广到所有Q一起统计答案依旧正确)

再用O(n)的for把他们加到原序列之中去,输出!

看一下复杂度,果然:O(常数*n).

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
const int maxn = 10+5;
int a[maxn] = {0,1,2,3,4,5,6,7,8,9,10};
int dis[maxn];

int main()
{
    int i;
    for(i=1; i<=10; i++)
    {
        printf("%d ",a[i]);
    }
    printf("\n");
    for(i=1; i<=10; i++)
    {
        dis[i] = a[i]-a[i-1];
    }
    dis[3] +=5;
    dis[9] -=5;
    for(i=1; i<=10; i++)
    {
        dis[i] = dis[i] +dis[i-1];
    }
    for(i=1; i<=10; i++)
        printf("%d ",dis[i]);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值