码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-06-23 17:37:10      阅读:101      评论:0      收藏:0      [点我收藏+]

标签:mes   表示   两种   输入   print   https   ret   printf   元素   

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 - 区间求和 - 前缀和

标签:mes   表示   两种   输入   print   https   ret   printf   元素   

原文地址:https://www.cnblogs.com/Yinku/p/11073411.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!