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());
}
原文地址:https://www.cnblogs.com/Yinku/p/11073411.html
时间: 2024-10-14 14:30:52