[洛谷P1438] 无聊的数列
题目类型:差分,线段树
传送门:>Here<
题意:给出一个数列,每次给一个区间对应的加上一个等差数列,并询问某一个元素目前的值。
解题思路
所谓差分,我个人的理解就是用\(O(1)\)的方法来维护前缀和,当然查询变为了\(O(n)\)。差分就好像将前缀和变成了一个数一样——当一段区间需要全部加上\(k\)时:差分数组某一位上\(+k\),意味着这之后的所有元素都将\(+k\)。就好像一条带子拖到最后了。因此我们如果仅仅操作一个区间的话,那么要把后面多出来的带子减掉,于是我们再另外加一条负的带子在后面。
刚才谈论整个区间都加一个相同的数。如果整个区间加的是一个等差数列呢?相当于这个区间内所加的数,每个都比前面的多加\(d\)。效果就等价于在差分数组中,令这个区间的每个元素加上\(d\)。然后末尾要减去末项。依然使用刚才的比喻,将那么多条相同的带子依次叠放,假设区间长度是\(l\),那么最后一个元素那里肯定放着\(l\)条带子了。而我们在最后需要把这\(l\)条带子全部减掉。
因此,如果用差分来维护这道题,我们来总结一下步骤:(按照题意,等差数列的更新方法是\(l \ r \ k \ d\),代表左端点,右端点,首项,公差;设差分数组为\(s\))
令\(s[l]+=k\)
令\(s[l+1..r]+=d\)
令\(s[r+1]-=k+d*(r-l)\)(末项)
由此我们发现,对于大多数的情况都是\(+d\),因此转化为一个区间更新的问题。差分数组的统计方法我们已经很熟悉了,需要从头遍历。因此元素\(p\)现在的值应该是:初始值 + \(s[1..p]\),因此转化为一个区间查询的问题
因此我们可以用线段树方便地\(O(logn)\)维护好
反思
一直以为差分和线段树维护的几乎是同一个东西,却从来没想过线段树可以用来维护差分!线段树维护差分,就好像求和的和。然而等差数列就好像是三维的一样,先由差分转化为二维,然后由线段树转化为线性。
正好像我们在找规律时所作的一样,差,差之差,差之差之差。那么这道题就好像倒过来,和,和的和,和的和的和……
Code
不需要建树,线段树写起来好像异常短小精悍……\(qwq\)
/*By DennyQi 2018*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 100010;
const int INF = 1061109567;
inline int Max(const int a, const int b){ return (a > b) ? a : b; }
inline int Min(const int a, const int b){ return (a < b) ? a : b; }
inline int read(){
int x = 0; int w = 1; register char c = getchar();
for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
if(c == '-') w = -1, c = getchar();
for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
}
int N,M,opt,l,r,x,y;
int a[MAXN];
int val[MAXN<<2],lazy[MAXN<<2];
struct SegmentTree{
inline void pushdown(int rt, int l, int r){
if(lazy[rt]){
int mid = (l+r)/2;
val[rt<<1] += lazy[rt] * (mid-l+1);
val[rt<<1|1] += lazy[rt] * (r-(mid+1)+1);
lazy[rt<<1] += lazy[rt];
lazy[rt<<1|1] += lazy[rt];
lazy[rt] = 0;
}
}
int query(int rt, int l, int r, int x, int y){
if(l > y || r < x) return 0;
if(x <= l && r <= y) return val[rt];
pushdown(rt, l, r);
int mid = (l+r)/2;
return query(rt<<1,l,mid,x,y) + query(rt<<1|1,mid+1,r,x,y);
}
void update(int rt, int l, int r, int x, int y, int k){
if(l > y || r < x) return;
if(x <= l && r <= y){
lazy[rt] += k;
val[rt] += (r-l+1) * k;
return;
}
pushdown(rt,l,r);
int mid = (l+r)/2;
update(rt<<1,l,mid,x,y,k), update(rt<<1|1,mid+1,r,x,y,k);
val[rt] = val[rt<<1] + val[rt<<1|1];
}
}qxz;
int main(){
N = read(), M = read();
for(int i = 1; i <= N; ++i){
a[i] = read();
}
while(M--){
opt = read();
if(opt == 1){
l = read(), r = read(), x = read(), y = read();
qxz.update(1,1,N,l,l,x);
qxz.update(1,1,N,l+1,r,y);
qxz.update(1,1,N,r+1,r+1,-(x+y*(r-l)));
}
else{
x = read();
printf("%d\n", qxz.query(1,1,N,1,x)+a[x]);
}
}
return 0;
}
[洛谷P1438] 无聊的数列的更多相关文章
- 洛谷P1438 无聊的数列 [zkw线段树]
题目传送门 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个数列{a[i]} ...
- 洛谷 P1438 无聊的数列
题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个数列{a[i]},支持两种操作: 1.1 ...
- 洛谷 P1438 无聊的数列 题解
原题链接 首先,我们考虑用差分解决问题. 用 \(x_i\) 表示原数列,\(a_i = x_i - x_{i-1}\) 那么,先普及一下差分: 如果我们只需要维护区间加值,单点求值的话,你会发现两个 ...
- 洛谷P1438 无聊的数列 (线段树+差分)
变了个花样,在l~r区间加上一个等差数列,等差数列的显著特点就是公差d,我们容易想到用线段树维护差分数组,在l位置加上k,在l+1~r位置加上d,最后在r+1位置减去k+(l-r)*d,这样就是在差分 ...
- Luogu P1438无聊的数列
洛谷 P1438无聊的数列 题目链接 点这里! 题目描述 维护一个数列\(a_i\),支持两种操作: 给出一个长度等于 \(r-l+1\)的等差数列,首项为\(k\) 公差为\(d\) 并将它对应加到 ...
- P1438 无聊的数列 (差分+线段树)
题目 P1438 无聊的数列 解析: 先考虑修改,用差分的基本思想,左端点加上首项\(k\),修改区间\((l,r]\)内每个数的差分数组都加上公差\(d\),最后的\(r+1\)再减去\(k+(r- ...
- P1438 无聊的数列
P1438 无聊的数列 链接 分析: 等差数列可加,首项相加,公差相加. 代码: #include<cstdio> #include<algorithm> #include&l ...
- [luogu P1438] 无聊的数列
[luogu P1438] 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个 ...
- 洛谷.2042.[NOI2005]维护数列(Splay)
题目链接 2017.12.24 第一次写: 时间: 2316ms (1268ms) 空间: 19.42MB (19.5MB)(O2) 注:洛谷测的时间浮动比较大 /* 插入一段数:将这些数先单独建一棵 ...
随机推荐
- ArcGIS API for JavaScript 4.2学习笔记[20] 使用缓冲区结合Query对象进行地震点查询【重温异步操作思想】
这个例子相当复杂.我先简单说说这个例子是干啥的. 在UI上,提供了一个下拉框.两个滑动杆,以确定三个参数,使用这三个参数进行空间查询.这个例子就颇带空间查询的意思了. 第一个参数是油井类型,第二个参数 ...
- Android为TV端助力 关于4.0之后不能直接获取SD卡外部存储路径的问题
Environment.getExternalStorageDirectory()是Android 2.x时代的产物,那时Android主流设备只有很小的内置存储器,然后都会外置一张sd卡,那时这个方 ...
- Android相机启动crash错误排查
一个Android的用到相机的service程序,在比较少的情况下会出现在系统启动时crash.log显示是在调用ACameraDevice_createCaptureSession时返回错误ACAM ...
- ASP.NET Core 入门教程 5、ASP.NET Core MVC 视图传值入门
一.前言 1.本教程主要内容 ASP.NET Core MVC 视图引擎(Razor)简介 ASP.NET Core MVC 视图(Razor)ViewData使用示例 ASP.NET Core MV ...
- Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数
Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数 目录 Pycharm使用技巧(转载) Python第一天 ...
- MySQL 执行计划中Extra(Using where,Using index,Using index condition,Using index,Using where)的浅析
关于如何理解MySQL执行计划中Extra列的Using where.Using Index.Using index condition,Using index,Using where这四者的区别 ...
- 深入理解Mysql索引的底层数据结构 B+ Tree (2)
sql查询 explain的详细用法 操作时间:寻道时间+旋转时间 引入索引:采用二叉树结构 把第二列做为索引生成二叉树结构,此时查询89 只做了两次io操作 但是mysql 为什么不用二叉树作为底层 ...
- C#-this关键字的功能之扩展方法
目录 1. 简介 2. 简单实例 3. 细节说明 1. 简介 我们的方法都是与声明他的类的相关联(我们现在写的各个方法都是在类中定义,所以我们调用方法都是用该方法所属类的实体对象调用). 在C#3.0 ...
- c/c++ 多线程 绕过mutex的保护
多线程 绕过mutex的保护 mutex,能够解决线程安全的问题,但它不是万能的.下面的例子虽然使用了mutex,但是恶意注入了一个外部函数,导致把被mutex保护的双向链表,让一个外部的指针指向了, ...
- EXTJS的使用
最近一段时间一直使用Extjs作为前端,通过HTTP与.net后端进行交互,今天总结一下EXTJS,方便以后复习. 1.概念: ExtJS可以用来开发RIA也即富客户端的AJAX应用,是一个用java ...