原题链接

首先,我们考虑用差分解决问题。

用 \(x_i\) 表示原数列,\(a_i = x_i - x_{i-1}\)

那么,先普及一下差分:

如果我们只需要维护区间加值,单点求值的话,你会发现两个重要等式:

\[a_i = x_i - x_{i-1}
\]

\[\sum_{j=1}^i a_j = x_i
\]

我们每次修改 \(l,r\) 区间增加 \(k\) 的话,你会发现:

则 \(l+1,r\) 这一段,所有的 \(a_i\) 都是不变的。这是因为:

\[(x_i + k) - (x_{i-1} + k) = x_i - x_{i-1} = a_i
\]

那么对于 \(a_l\) 这个点,显然:

\[(x_l + k) - x_{l-1} = (x_l - x_{l-1}) + k = a_l + k
\]

对于 \(a_{r+1}\) 这个点,显然:

\[a_{r+1} - (a_r + k) = (a_{r+1} - a_r) - k = a_{r+1} - k
\]

这是正常的差分。

可是,我们现在加上了一个 等差数列 。由于等差数列的性质,显然每个点加上的值比前一个点多 \(d\).

所以, \(l+1 , r\) 这一段, \(a_i \gets a_i + d\) .

那么对于 \(a_l\) 这个点:

\[(x_l + k) - x_{l-1} = (x_l - x_{l-1}) + k = a_i + k
\]

对于 \(a_{r+1}\) 这个点:

\[x_{r+1} - (x_r + k + (r-l) \times d) = (x_{r+1} - x_r) - (k + (r-l) \times d) = a_{r+1} - (k + (r-l) \times d)
\]

下面我们考虑单点查询。

\[x_i = \sum_{j=1}^i a_j
\]

显然,我们用 线段树 维护 \(x\) 数组的区间修改和区间求和。

时间复杂度: \(O(n \log n + m \log n)\).

空间复杂度: \(O(n)\).

  1. #pragma GCC optimize(2)
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. typedef long long ll;
  5. const int N=1e5+1;
  6. #define L (i<<1)
  7. #define R i<<1|1
  8. inline ll read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
  9. ll x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
  10. struct tree{
  11. int l,r; ll tag;
  12. ll sumi;
  13. };
  14. tree t[4*N];
  15. int n,m,x[N]; //原数组
  16. ll a[N]; //差分后的数组
  17. inline void update(int i) {
  18. t[i].sumi=t[L].sumi+t[R].sumi;
  19. } //更新
  20. inline void pass(int i,ll x) {
  21. t[i].tag+=x;
  22. t[i].sumi+=x*(t[i].r-t[i].l+1);
  23. }
  24. inline void pushdown(int i) {
  25. pass(L,t[i].tag);
  26. pass(R,t[i].tag);
  27. t[i].tag=0;
  28. } //下传标记
  29. inline void build_tree(int i,int l,int r) {
  30. t[i].l=l; t[i].r=r;
  31. if(l==r) {
  32. t[i].sumi=a[l]; t[i].tag=0;
  33. return;
  34. } int mid=(l+r)>>1;
  35. build_tree(L,l,mid);
  36. build_tree(R,mid+1,r);
  37. update(i);
  38. } //建树
  39. inline ll query(int i,int l,int r) {
  40. if(l<=t[i].l && t[i].r<=r) return t[i].sumi;
  41. int mid=(t[i].l+t[i].r)>>1; ll ans=0;
  42. pushdown(i);
  43. if(l<=mid) ans+=query(L,l,r);
  44. if(r>mid) ans+=query(R,l,r);
  45. return ans;
  46. } //询问
  47. inline void change(int i,int l,int r,int x) {
  48. if(l<=t[i].l && t[i].r<=r) {
  49. t[i].sumi+=x*(t[i].r-t[i].l+1);
  50. t[i].tag+=x; return ;
  51. } pushdown(i);
  52. int mid=(t[i].l+t[i].r)>>1;
  53. if(l<=mid) change(L,l,r,x);
  54. if(r>mid) change(R,l,r,x);
  55. update(i);
  56. } //修改
  57. int main(){
  58. n=read(),m=read();
  59. for(int i=1;i<=n;i++) x[i]=read();
  60. for(int i=1;i<=n;i++) a[i]=ll(x[i]-x[i-1]);
  61. // for(int i=1;i<=n;i++) printf("%d ",a[i]);
  62. // putchar('\n');
  63. build_tree(1,1,n);
  64. while(m--) {
  65. int opt=read();
  66. ll l,r,k,d;
  67. if(opt==1) {
  68. l=read(),r=read(),k=read(),d=read();
  69. change(1,l,l,k);
  70. if(r>l) change(1,l+1,r,d);
  71. if(r-n) change(1,r+1,r+1,-(k+(r-l)*d));
  72. //维护
  73. } else printf("%lld\n",query(1,1,read()));
  74. }
  75. return 0;
  76. }

洛谷 P1438 无聊的数列 题解的更多相关文章

  1. 洛谷P1438 无聊的数列 [zkw线段树]

    题目传送门 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个数列{a[i]} ...

  2. 洛谷 P1438 无聊的数列

    题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个数列{a[i]},支持两种操作: 1.1 ...

  3. [洛谷P1438] 无聊的数列

    题目类型:差分,线段树 传送门:>Here< 题意:给出一个数列,每次给一个区间对应的加上一个等差数列,并询问某一个元素目前的值. 解题思路 所谓差分,我个人的理解就是用\(O(1)\)的 ...

  4. 洛谷P1438 无聊的数列 (线段树+差分)

    变了个花样,在l~r区间加上一个等差数列,等差数列的显著特点就是公差d,我们容易想到用线段树维护差分数组,在l位置加上k,在l+1~r位置加上d,最后在r+1位置减去k+(l-r)*d,这样就是在差分 ...

  5. Luogu P1438无聊的数列

    洛谷 P1438无聊的数列 题目链接 点这里! 题目描述 维护一个数列\(a_i\),支持两种操作: 给出一个长度等于 \(r-l+1\)的等差数列,首项为\(k\) 公差为\(d\) 并将它对应加到 ...

  6. 洛谷P1783 海滩防御 分析+题解代码

    洛谷P1783 海滩防御 分析+题解代码 题目描述: WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和 ...

  7. P1438 无聊的数列 (差分+线段树)

    题目 P1438 无聊的数列 解析: 先考虑修改,用差分的基本思想,左端点加上首项\(k\),修改区间\((l,r]\)内每个数的差分数组都加上公差\(d\),最后的\(r+1\)再减去\(k+(r- ...

  8. P1438 无聊的数列

    P1438 无聊的数列 链接 分析: 等差数列可加,首项相加,公差相加. 代码: #include<cstdio> #include<algorithm> #include&l ...

  9. [luogu P1438] 无聊的数列

    [luogu P1438] 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个 ...

随机推荐

  1. 添砖加瓦:snappy无损压缩算法

    一.简介 Snappy(旧称:Zippy)是Google基于LZ77的思路用C++语言编写的快速数据压缩与解压程序库,并在2011年开源.其目标并非最大压缩率或与其他压缩程序的兼容性,而是非常高的速度 ...

  2. Gradle的依赖方式——Lombok在Gradle中的正确配置姿势

    写过java的都知道,lombok几乎在项目中处于不可或缺的一部分,但是lombok在Gradle的项目中配置并非人人都知道. 很多人在项目依赖中直接这样写 1 compile "org.p ...

  3. C++与引用2

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  4. css雪碧图压缩

    cssgaga下载地址 链接: https://pan.baidu.com/s/1Q9xH_XzumIc7vTLCZ3tr5A 提取码: stqe CssGaga功能特性 合并import的CSS文件 ...

  5. AAAI 2020论文分享:通过识别和翻译交互打造更优的语音翻译模型

    2月初,AAAI 2020在美国纽约拉开了帷幕.本届大会百度共有28篇论文被收录.本文将对其中的机器翻译领域入选论文<Synchronous Speech Recognition and Spe ...

  6. percona-toolkit 之 【pt-query-digest】介绍

    背景: 做为一个MySQL DBA,分析慢查询是日常主要的工作之一,之前一直使用mysqlsla作为分析慢查询的, 因为简单并且也能满足自己对慢查询分析的要求,对于另一个工具pt-query-dige ...

  7. 什么是x86什么是x64 它们有什么区别

    1.内存寻址不同: 32位系统,最大支持3.5G内存,如果在32位系统中使用4G或更大的内存,电脑最多只可以识别3.4G左右可用,而64位系统最大可以支持128G大内存. 2.运算速度不同: 64位系 ...

  8. 如何用Postman做接口自动化测试

    目录 前言 什么是自动化测试 自动测试测试分类 为什么需要自动化测试 Postman自动化测试演示 1.新建集合 2.新建接口 3.填写自动化测试脚本 4.录入所有接口 5.执行自动化测试 前言 什么 ...

  9. jdbc Template 存储过程 返回多个结果 ,out 输出参数

    public ReportVo getReport() { //执行存储过程 ReportVo reportVo=jdbcTemplate.execute(new CallableStatementC ...

  10. C#版免费离线人脸识别——虹软ArcSoft V3.0

    [温馨提示] 本文共678字(不含代码),8张图.预计阅读时间需要6分钟. 1. 前言 人脸识别&比对发展到今天,已经是一个非常成熟的技术了,而且应用在生活的方方面面,比如手机.车站.天网等. ...