\(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. python学习之老男孩python全栈第九期_day017知识点总结——初识递归、算法

    一. 递归函数 如果一个函数在内部调用自身本身,这个函数就是递归函数. 最大递归深度默认是997 -- python从内存角度出发做得限制(而不是程序真的报错),最大深度可以修改 def func(n ...

  2. 说说JSON和JSONP区别

    前言 由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现. 当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Socke ...

  3. 洛谷P3763 [TJOI2017]DNA(后缀数组 RMQ)

    题意 题目链接 Sol 这题打死我也不会想到后缀数组的,应该会全程想AC自动机之类的吧 但知道这题能用后缀数组做之后应该就不是那么难了 首先把\(S\)和\(S0\)拼到一起跑,求出Height数组 ...

  4. .NET 跨平台服务端资料

    OWIN Web API:  http://www.asp.net/web-api/overview/hosting-aspnet-web-api/use-owin-to-self-host-web- ...

  5. python单下划线、双下划线、头尾双下划线说明:

      单下划线.双下划线.头尾双下划线说明: __foo__: 定义的是特殊方法,一般是系统定义名字 ,类似 __init__() 之类的. _foo: 以单下划线开头的表示的是 protected 类 ...

  6. JavaScript 小实例 - 表单输入内容检测,对页面的增删改

    JavaScript 小实例 - 表单输入内容检测,对页面的增删改 效果体验地址:https://xpwi.github.io/js/JavaScript01/jsForm.html 功能: 1.向页 ...

  7. Python爬虫教程-08-post介绍(百度翻译)(下)

    Python爬虫教程-08-post介绍(下) 为了更多的设置请求信息,单纯的通过urlopen已经不太能满足需求,此时需要使用request.Request类 构造Request 实例 req = ...

  8. es6常见特性

    Parameters(参数) in ES6 Template Literals (模板文本)in ES6 Multi-line Strings (多行字符串)in ES6 Destructuring  ...

  9. Visual studio 2015已经停止工作无限重启

    今天遇到一个问题,某个文件在撤销的时候vs报错,然后提示到路径 “C:\Users\username\AppData\Roaming\Microsoft\VisualStudio\14.0\***.x ...

  10. Java学习---JBPM[工作流]学习

    点击参考 更多参考 链接:https://pan.baidu.com/s/1A1AH5sXu7yhV3mncpH4Z6w 密码:88zw