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. node向html模板发送数据

    node向html模板发送数据 给模板传递数据 router.get('/', function(req, res, next) { res.render('index', { title: '张三' ...

  2. JS高阶函数的理解(函数作为参数传递)

    JS高阶函数的理解 高阶函数是指至少满足下列条件之一的函数. · 函数可以作为参数被传递 · 函数可以作为返回值输出 一个例子,我们想在页面中创建100个div节点,这是一种写法.我们发现并不是所有用 ...

  3. Cocos2d-x中屏幕截取

    类似半屏幕文字向上滚动,到一定位置,逐渐消失 这里用到了CCLayer的visit()方法 首先新建一个类TxtLayer  继承CCLayer class TxtLayer : public coc ...

  4. BZOJ 2431 [HAOI2009]逆序对数列:dp 逆序对

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2431 题意: 给定n,k,问你有多少个由1~n组成的排列,使得逆序对个数恰好为k个. 题解 ...

  5. spring学习(4)

    在spring容器内拼凑bean叫做装配.装配bean的时候,需要告诉容器哪些bean以及容器如何使用依赖注入将它们配合在一起. 上下文定义文件的根元素是<beans>,<beans ...

  6. mysql 如何创建索引

    mysql 如何创建索引 一.总结 一句话总结:MySQL中可以使用alter table这个SQL语句来为表中的字段添加索引. 使用alter table语句来为表中的字段添加索引的基本语法是:AL ...

  7. Abp模块分析

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

  8. BEC listen and translation exercise 44

    But over the past 70 years or so, there's been a massive increase in one type of crime which was wha ...

  9. C++11特性 gcc源码包

    1.下载gcc最新的源码包  2.解压缩 tar -xf gcc-4.9.1.tar.gz 3. cd gcc-4.9.1 4.运行download_prerequisites脚本, ./contri ...

  10. linux命令学习笔记(50):crontab命令

    前一天学习了 at 命令是针对仅运行一次的任务,循环运行的例行性计划任务,linux系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个 ...