\(Link\)

\(\color{red}{\mathcal{Description}}\)

给你一个数列,要求支持单点查询\(and\)区间加等差数列。

\(\color{red}{\mathcal{Solution}}\)

哈哈哈哈这个题十分的有意思,至于为什么有意思等会儿再说~

其实我们观察这两个操作,单点查询……就是那个\(naive\)的单点查询,那么区间加等差数列呢?我们可以思考一下等差数列的性质——存在公差。不妨考虑差分

\(emmm\)发现我好像还没有在博客园里提过差分……那么就整一整吧正好我好久没捯饬这玩意儿了\(qwq\)

差分

其实就是对于一个给定的数列\(base\),我们用另一个数组\(dif_i\)记录\(base_i - base_{i - 1}\),从而我们可以通过\(dif\)反向得到$$base_i = \sum_{j = 1}^{i}{dif_j}$$呐,我们如果有区间加减这种操作或者其他的,我们可以通过操作\(dif_i\)和\(dif_{j + 1}\)来起到对区间\(i\)~\(j\)打标记的作用。关键就是一定要是单点查询……区间查询仿佛也可以做?但是有点麻烦略略略。

回到这个题,我们的线段树可以建在数列的差分数组上。然后区间加等差数列的时候,我们就让\(dif_L += D\),\(dif_{L+1...R} += K\),\(dif_{R+1} -= (K \times (R - L) + D)\)很显然。如果要是区间查询的话,我们就直接线段树求个$$ans = \sum_{i = 1}^{P}{dif_i}$$但是在程序实现的时候,笔者在此偷了个懒,没有初始化\(dif\)数组,那么我们就需要在区间查询的时候改成这样$$ans = \sum_{i = 1}^{P}{dif_i} + base_P$$

\(Code\)

#include <cstdio>
#include <iostream>
#define mid ((l + r) >> 1) using namespace std ;
const int MAXN = 100050 ;
int N, M, P, mark, i, base[MAXN] ;
int L, R, K, D, dif[MAXN << 2], tag[MAXN << 2] ; inline int qrd(){
int k = 0, f = 1 ; char c = getchar() ;
while(!isdigit(c)) {if(c == '-') f = -1; c = getchar() ;}
while(isdigit(c)) k = (k << 1) + (k << 3) + c - 48, c = getchar() ;
return k * f ;
}
inline void p_u(int rt){dif[rt] = dif[rt << 1] + dif[rt << 1 | 1] ;}
inline void p_d(int rt, int l, int r){
if(tag[rt]){
dif[rt << 1] += tag[rt] * (mid - l + 1) ;
dif[rt << 1 | 1] += tag[rt] * (r - mid) ;
tag[rt << 1] += tag[rt] ;
tag[rt << 1 | 1] += tag[rt] ;
tag[rt] = 0 ;
}
}
void update(int rt, int l, int r, int ul, int ur, int k){
if(ul <= l && r <= ur){
tag[rt] += k ;
dif[rt] += k * (r - l + 1) ;
return ;
}p_d(rt, l, r) ;
if(ul <= mid) update(rt << 1, l, mid, ul, ur, k) ;
if(ur > mid) update(rt << 1 | 1, mid + 1, r, ul, ur, k) ;
p_u(rt) ;
}
int query(int rt, int l, int r, int ql, int qr){
if(ql <= l && r <= qr){return dif[rt] ;}p_d(rt, l, r) ;
int res = 0 ;
if(ql <= mid) res += query(rt << 1, l, mid, ql, qr) ;
if(qr > mid) res += query(rt << 1 | 1, mid + 1, r, ql, qr) ;
return res ;
}
int main(){
N = qrd(), M = qrd() ;
for(i = 1; i <= N; i ++) base[i] = qrd() ;
for(i = 1; i <= M; i ++){
cin >> mark ;
if (mark == 1) {
L = qrd(), R = qrd(), K = qrd(), D = qrd() ;
update(1, 1, N, L, L, K) ;
if (R > L) update(1, 1, N, L + 1, R, D) ;
if (R != N) update(1, 1, N, R + 1, R + 1, -(R - L) * D - K) ;
}
else {
P = qrd() ;
cout << base[P] + query(1, 1, N, 1, P) << endl ;
}
}
}

\(upd:\)诶我好像是忘记说哪里好玩儿了……

这个题前不久\(qyf\)给我们讲的时候忘记怎么做了,然后在经过讨论之后,觉得wx的想法不错,于是当时就奉为了正解。当时的想法好像是在\(base\)上建一棵线段树,push_down的时候我们记录一下两个子区间的第一个元素应该加多少&公差,整个区间暴力加和。

现在想想吧……好像好麻烦的样子……并且因为它是单点查询,中间维护那么多次区间和根本没必要……复杂度的话…也是\(nlogn\)?应该是吧……但是好像很蠢的样子qwq

啊……真怀念当时啊……

[LuoguP1438]无聊的数列(差分+线段树/树状数组)的更多相关文章

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

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

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

    传送门 解题思路 区间加等差数列+单点询问,用差分+线段树解决,线段树里维护的就是差分数组,区间加等差数列相当于在差分序列中l位置处+首项的值,r+1位置处-末项的值,中间加公差的值,然后单点询问就相 ...

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

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

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

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

  5. CodeForces -163E :e-Government (AC自动机+DFS序+树状数组)

    The best programmers of Embezzland compete to develop a part of the project called "e-Governmen ...

  6. 线段树+差分【p1438】无聊的数列

    Description 维护一个数列{a[i]},支持两种操作: 1.1 L R K D:给出一个长度等于R-L+1的等差数列,首项为K,公差为D,并将它对应加到a[L]~a[R]的每一个数上.即:令 ...

  7. BZOJ_4636_蒟蒻的数列_线段树+动态开点

    BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...

  8. 【bzoj5028】小Z的加油店 扩展裴蜀定理+差分+线段树

    题目描述 给出 $n$ 个瓶子和无限的水,每个瓶子有一定的容量.每次你可以将一个瓶子装满水,或将A瓶子内的水倒入B瓶子中直到A倒空或B倒满.$m$ 次操作,每次给 $[l,r]$ 内的瓶子容量增加 $ ...

  9. COGS 2638. 数列操作ψ 线段树

    传送门 : COGS 2638. 数列操作ψ 线段树 这道题让我们维护区间最大值,以及维护区间and,or一个数 我们考虑用线段树进行维护,这时候我们就要用到吉司机线段树啦 QAQ 由于发现若干次an ...

随机推荐

  1. 您只能在 HTML 输出流中使用 document.write,啥意思

    JavaScript :写入到HTML输出语法 注意:只能在HTML输出中使用,如果在文档已经加载后使用(比如在函数中)  会覆盖到整个文档 <!DOCTYPE html> <htm ...

  2. SPOJ:NSUBSTR - Substrings

    题面 字符串$ S \(最多包含\) 25 \(万个小写拉丁字母.我们将\) F(x) \(定义为长度为\) x \(的某些字符串出现在\) s \(中的最大次数.例如,对于字符串\) "a ...

  3. 20个实用便捷的CSS3工具、库及实例

    编者按:坊间传闻,有本CSS的高手炼成秘籍在江湖失传已久,书中所载,多为最新的惊人技术与实例示范,是为集大成者,一旦学成,代码效率猛增,功力提升数倍,今日偶获,不敢怠慢,赶紧发到优设,望人人受益.说人 ...

  4. IE、火狐、谷歌浏览器下兼容统一select样式

    项目开发时,对于不同浏览器下的select样式不统一问题,各种查,这里记录一下,项目已使用 IE浏览器下样式: 火狐浏览器下样式: 谷歌浏览器下样式: 上代码: 1.html 2.css 至此,大功告 ...

  5. 在PHP中使用加密技术

    Gpg4win 是一款基于 GPG 的非对称加密软件.非对称加密方式,简单理解就是用公钥加密文件,用私钥解密文件.如果你需要发送加密信息,首先获取接收者的公钥,然后利用该公钥加密后传递,对方利用对应的 ...

  6. springboot整合fastdfs实现上传和下载

    FastDFS_Client源码 https://github.com/tobato/FastDFS_Client 友情提示:由于FastDFS_Client这个源码不是很多,并且目前没有找到相关文档 ...

  7. xml-treeview转换

    XML——>treeciew using System; using System.Collections.Generic; using System.Text; using System.Wi ...

  8. 10 套华丽的 CSS3 按钮推荐

    在过去的Web开发中,通常使用Photoshop来设计按钮的样式.不过随着CSS3技术的发展,你完全可以通过几行代码来定制一个漂亮的按钮,并且还可以呈现渐变.框阴影.文字阴影等效果.此类按钮最大的优势 ...

  9. 封装和 property方法

    封装其实就是一个类用双下划线把自己的属性或者方法给限制住 不让其他的类直接调用或者修改  必须通过这个类来进行操作,这个类通过双下划线__把自己的属性和方法给限制住了 封装就是私有的过程 把父类中的属 ...

  10. 克隆对象__clone()方法

    有的时候我们需要在一个项目里面,使用两个或多个一样的对象,如果你使用“new”关键字重新创建对象的话,再赋值上相同的属性,这样做比较烦琐而且也容易出错,所以要根据一个对象完全克隆出一个一模一样的对象, ...