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,解除这个三角形的时候就要把它的贡献一并解除掉。显然贡献就是区间长。
所以这个数据结构可以叫做“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 - 区间求和 - 前缀和的更多相关文章
- vijos1740 聪明的质监员 (二分、区间求和)
http://www.rqnoj.cn/problem/657 https://www.vijos.org/p/1740 P1740聪明的质检员 请登录后递交 标签:NOIP提高组2011[显示标签] ...
- poj3468树状数组的区间更新,区间求和
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 47174 ...
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- POJ 2823 Sliding Window 线段树区间求和问题
题目链接 线段树区间求和问题,维护一个最大值一个最小值即可,线段树要用C++交才能过. 注意这道题不是求三个数的最大值最小值,是求k个的. 本题数据量较大,不能用N建树,用n建树. 还有一种做法是单调 ...
- POJ 3468 A Simple Problem with Integers(线段树 成段增减+区间求和)
A Simple Problem with Integers [题目链接]A Simple Problem with Integers [题目类型]线段树 成段增减+区间求和 &题解: 线段树 ...
- LightOJ 1112 Curious Robin Hood (单点更新+区间求和)
http://lightoj.com/volume_showproblem.php?problem=1112 题目大意: 1 i 将第i个数值输出,并将第i个值清0 2 i v ...
- 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 ...
- poj3468 A Simple Problem with Integers(线段树模板 功能:区间增减,区间求和)
转载请注明出处:http://blog.csdn.net/u012860063 Description You have N integers, A1, A2, ... , AN. You need ...
- D 区间求和 [数学 树状数组]
D 区间求和 题意:求 \[ \sum_{k=1}^n \sum_{l=1}^{n-k+1} \sum_{r=l+k-1}^n 区间前k大值和 \] 比赛时因为被B卡了没有深入想这道题 结果B没做出来 ...
随机推荐
- Build Antlr4 projects with eclipse java project template.
from:https://shijinglu.wordpress.com/2015/01/22/build-antlr4-projects-with-eclipse-java-project-temp ...
- 百度地图省市县乡镇街道对应ZOOM级别
百度地图省市县乡镇街道对应ZOOM级别
- Hibernate学习---第七节:关联关系
一.关联关系一对一外键(双向) 1.实体类,代码如下: package learn.hibernate.bean; import java.util.Date; /** * 持久化类设计 * 注意: ...
- Sqlite表结构读取工具,word批量转html,在线云剪贴板,文件批量提取工具;
工欲善其事必先利其器,本周为您推荐工具排行 Sqlite表结构读取工具,word批量转html,在线云剪贴板,文件批量提取工具: 本周我们又要发干货了,准备好接受了吗? 为什么是干货,就是因为 ...
- ACM学习历程—HDU1030 Delta-wave(数学)
Description A triangle field is numbered with successive integers in the way shown on the picture be ...
- bzoj 2084: Antisymmetry 回文自动机
题目: Description 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作"反对称"字符串.比如00001111和010101就是反对称的 ...
- InvalidOperationException: out of sync
C#中不能在集合的迭代中修改集合数据
- [bzoj2142]礼物(扩展lucas定理+中国剩余定理)
题意:n件礼物,送给m个人,每人的礼物数确定,求方案数. 解题关键:由于模数不是质数,所以由唯一分解定理, $\bmod = p_1^{{k_1}}p_2^{{k_2}}......p_s^{{k_ ...
- Python 中list, dictionary 与 file相互操作
Python的list,dictionary可以写入file, 也可以从file中读取. 关于list: 1)写入文件 self.existedBlog.write("you ...
- 清理:db上面的过期的binlog,释放磁盘空间。 (转)
如果10台以内的db的话,自己手动ssh进去,clean就足以,但是上百台呢,就要写脚本了.大概思路:在 一台db跳转机上面, 写一个脚本,访问slave,远程获取正在复制的master上面的binl ...