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,解除这个三角形的时候就要把它的贡献一并解除掉。显然贡献就是区间长。

所以这个数据结构可以叫做“LD三角形区间修改前缀和”

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; inline ll read() {
ll x = 0;
bool 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;
} inline void _write(ll x) {
if(x > 9)
_write(x / 10);
putchar(x % 10 + '0');
} inline void write(ll x) {
if(x < 0) {
putchar('-');
x = -x;
}
_write(x);
putchar('\n');
} /*--- ---*/ const int MAXM = 1000000;
ll df1[MAXM+5];
int df2[MAXM+5]; inline void update(int l, int r, ll v) {
df1[l]+=v;
df1[r+1]-=v;
} inline void update2(int l, int r) {
df2[l]+=1;
df2[r+1]-=1;
df1[r+1]-=(r-l+1);
} inline ll calc() {
ll ans=0;
int curd=0;
ll curs=0;
for(int i=1;i<=MAXM;i++){
curd+=df2[i];
curs+=curd;
curs+=df1[i];
if(curs>ans)
ans=curs;
}
return ans;
} int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
//freopen("Yinku.out","w",stdout);
#endif // Yinku
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);
}
}
write(calc());
}

要是少一个数量级其实可以线段树:

#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 a[MAXM + 5];
ll lazy[(MAXM << 2) + 5];
int lazy2[(MAXM << 2) + 5]; inline void push_down(int o, int l, int r) {
if(lazy[o] || lazy2[o]) {
lazy[o << 1] += lazy[o];
lazy[o << 1 | 1] += lazy[o];
int m = (l + r) >> 1;
lazy2[o << 1] += lazy2[o];
lazy2[o << 1 | 1] += lazy2[o];
lazy[o << 1 | 1] += (m - l + 1) * lazy2[o];
lazy[o] = 0;
lazy2[o] = 0;
}
} void build() {
memset(a, 0, sizeof(a));
memset(lazy, 0, sizeof(lazy));
memset(lazy2, 0, sizeof(lazy2));
} void update(int o, int l, int r, int a, int b, ll v) {
if(a <= l && r <= b) {
lazy[o] += v;
return;
} else {
push_down(o, l, r);
int m = (l + r) >> 1;
if(a <= m)
update(o << 1, l, m, a, b, v);
if(b >= m + 1)
update(o << 1 | 1, m + 1, r, a, b, v);
}
} void update2(int o, int l, int r, int a, int b, int h) {
//这个区间底下包含一个高为h的矩形然后上面是一个三角形,最左侧恰好有h+1个方块
if(a <= l && r <= b) {
lazy[o] += h;
lazy2[o]++;
return;
} else {
push_down(o, l, r);
int m = (l + r) >> 1;
if(a <= m)
update2(o << 1, l, m, a, b, h);
//左侧底下方块是一样的
if(b >= m + 1)
update2(o << 1 | 1, m + 1, r, a, b, h + m - a + 1);
//右侧多m-a+1个方块
}
} void all_pushdown(int o, int l, int r) {
if(l == r) {
a[l] += lazy[o] + lazy2[o];
} else {
push_down(o, l, r);
int m = (l + r) >> 1;
all_pushdown(o << 1, l, m);
all_pushdown(o << 1 | 1, m + 1, r);
}
} 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(1,1,1000000,l,r,x);
}
else{
update2(1,1,1000000,l,r,0);
}
}
all_pushdown(1,1,1000000);
ll maxans=a[1];
for(int i=2;i<=1000000;i++){
if(a[i]>maxans)
maxans=a[i];
}
printf("%lld\n",maxans);
}

GXU - 7D - 区间求和 - 前缀和的更多相关文章

  1. vijos1740 聪明的质监员 (二分、区间求和)

    http://www.rqnoj.cn/problem/657 https://www.vijos.org/p/1740 P1740聪明的质检员 请登录后递交 标签:NOIP提高组2011[显示标签] ...

  2. poj3468树状数组的区间更新,区间求和

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 47174   ...

  3. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  4. POJ 2823 Sliding Window 线段树区间求和问题

    题目链接 线段树区间求和问题,维护一个最大值一个最小值即可,线段树要用C++交才能过. 注意这道题不是求三个数的最大值最小值,是求k个的. 本题数据量较大,不能用N建树,用n建树. 还有一种做法是单调 ...

  5. POJ 3468 A Simple Problem with Integers(线段树 成段增减+区间求和)

    A Simple Problem with Integers [题目链接]A Simple Problem with Integers [题目类型]线段树 成段增减+区间求和 &题解: 线段树 ...

  6. LightOJ 1112 Curious Robin Hood (单点更新+区间求和)

    http://lightoj.com/volume_showproblem.php?problem=1112 题目大意: 1 i        将第i个数值输出,并将第i个值清0 2 i v     ...

  7. POJ 3468 A Simple Problem with Integers(线段树区间求和)

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

  8. poj3468 A Simple Problem with Integers(线段树模板 功能:区间增减,区间求和)

    转载请注明出处:http://blog.csdn.net/u012860063 Description You have N integers, A1, A2, ... , AN. You need ...

  9. D 区间求和 [数学 树状数组]

    D 区间求和 题意:求 \[ \sum_{k=1}^n \sum_{l=1}^{n-k+1} \sum_{r=l+k-1}^n 区间前k大值和 \] 比赛时因为被B卡了没有深入想这道题 结果B没做出来 ...

随机推荐

  1. JavaScript中call、apply个人理解

    JavaScript中call.apply个人理解 一句话即通俗的说:call.apply 是为了改变this的状态而存在的 }; } function personInfo(name,age){ t ...

  2. 英语发音规则---Y字母

    英语发音规则---Y字母 一.总结 一句话总结: 1.Y字母在单词最前面读发[j]? yes /jes/ [jɛs] n. 是 yard /jɑːd/ [jɑd] n. 院子 yellow /'jel ...

  3. Abp模块分析

    1.什么是模块? 模块化是一种处理复杂系统分解为更好的可管理模块的方式.模块化用来分割,组织和打包软件.每个模块完成一个特定的子功能,所有的模块按某种方法组装起来,成为一个整体,完成整个系统所要求的功 ...

  4. 201621123014《JAVA程序设计》第2周学习总结

    1. 本周学习总结 引用数据类型:JAVA定义字符串实际上是创建字符串的引用,将引用指向需要的字符串. 字符串常量池:直接对引用赋值时,会先在字符串中搜索是否有这个对象,已有则不创建直接指向它. St ...

  5. Android中的优化技巧

    高效地利用线程 1.在后台取消一些线程中的动作 我们知道App运行过程中所有的操作都默认在主线程(UI线程)中进行的,这样App的响应速度就会受到影响.会导致程序陷入卡顿.死掉甚至会发生系统错误. 为 ...

  6. 解决编译warning:warning: ‘MeteringUnit::voltage_gain_’ will be initialized after [-Wreorder]

    问题: 环境:ubuntu 12.04,g++版本4.6.3,编译目标文件时出现warnings: u1204@u1204-zhw:~/hwsvn/2sw/4prj_mips/UCP_rt5350/s ...

  7. Qt Quick之Canvas

    QML中的Canvas,俗称画布,它用来定义一个绘图区域,可以使用ECMAScript代码来绘制直线,矩形,贝塞尔曲线,弧线,图片,文字等图元,还可以为这些图元应用填充颜色和边框颜色,甚至还可以进行低 ...

  8. ACM学习历程——ZOJ 3829 Known Notation (2014牡丹江区域赛K题)(策略,栈)

    Description Do you know reverse Polish notation (RPN)? It is a known notation in the area of mathema ...

  9. codevs 3372 选学霸

    3372 选学霸  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果 ...

  10. 【C&C++】查看代码运行时间

    查看代码运行时间有助于更好地优化项目代码 1. Windows平台 windows平台下有两种方式,精度有所不同,都需要包含<windows.h>头文件 1) DWORD GetTickC ...