GXU - 7D - 区间求和 - 前缀和

Posted yinku

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GXU - 7D - 区间求和 - 前缀和相关的知识,希望对你有一定的参考价值。

https://oj.gxu.edu.cn/contest/7/problem/D

描述
有一个所有元素皆为0的数组A,有两种操作:
1 l r x表示将A区间[l,r]内所有数加上x;
2 l r表示将A区间[l,r]内从左往右数第i个数加上i;

给出m个操作,请输出操作结束后A中的最大值。

输入
第一行一个整数m,表示操作的个数
接下来有m行,表示操作的内容,具体格式与题目中一致

0<=m<=10^6
1<=l<=r<=10^6
0<=x<=10^9

输出
输出一个整数,表示所有操作之后A中的最大值

思路,差分,难点在于三角形怎么处理。
其实也不难,计算一下有几个三角形在哪里出现又消失就可以了。当三角形消失的时候解除掉三角形对当前的影响就足够了。

首先对差分求前缀和可以复原原数组,这个简单。

那么对三角形数量差分求前缀和可以复原每个区间的三角形的数量。

发现每一个三角形会使得前缀和增加1,解除这个三角形的时候就要把它的贡献一并解除掉。显然贡献就是区间长。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

inline ll read() 
    ll x = 0;
    //int f = 0;
    char c;
    do 
        c = getchar();
        /*if(c == '-')
            f = 1;*/
     while(c < '0' || c > '9');
    do 
        x = (x << 3) + (x << 1) + c - '0';
        c = getchar();
     while(c >= '0' && c <= '9');
    //return f ? -x : x;
    return x;


inline void _write(int x) 
    if(x > 9)
        _write(x / 10);
    putchar(x % 10 + '0');


inline void write(int x) 
    if(x < 0) 
        putchar('-');
        x = -x;
    
    _write(x);
    putchar('\n');


/*---  ---*/

const int MAXM = 1000000;
ll df1[MAXM+5],df2[2][MAXM+5];

void build() 
    memset(df1, 0, sizeof(df1));
    memset(df2, 0, sizeof(df2));


void update(int l, int r, ll v) 
    df1[l]+=v;
    df1[r+1]-=v;


void update2(int l, int r) 
    df2[0][l]+=1;
    //从l位置开始一个三角形,三角形数量增加
    df2[0][r+1]-=1;
    //从r+1位置解除一个三角形
    df2[1][r+1]-=(r-l+1);
    //该三角形目前累计了区间长的数字,从这里开始解除掉


ll calc() 
    ll ans=0;
    ll curdelta=0;//当前的三角形数
    ll cursum=0;//当前累计的叠加量
    for(int i=1;i<=1000000;i++)
        cursum+=df1[i];
        curdelta+=df2[0][i];
        cursum+=curdelta;
        cursum+=df2[1][i];
        if(cursum>ans)
            ans=cursum;
    
    return ans;


int main() 
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
    //freopen("Yinku.out","w",stdout);
#endif // Yinku
    //sieve();
    build();
    int m=read();
    while(m--)
        int op=read(),l=read(),r=read();
        if(op==1)
            int x=read();
            update(l,r,x);
        
        else
            update2(l,r);
        
    

    printf("%lld\n",calc());

以上是关于GXU - 7D - 区间求和 - 前缀和的主要内容,如果未能解决你的问题,请参考以下文章

树状数组2 - 区间加 单点求和

资瓷区间修改+区间求和的树状数组(一维/二维)

树状数组P3372 模板线段树 1

树状数组区间更新

单调栈 前缀和 异或7.21序列求和

线段树入门