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 - 区间求和 - 前缀和的主要内容,如果未能解决你的问题,请参考以下文章