[LuoguP1438]无聊的数列(差分+线段树/树状数组)
\(\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]无聊的数列(差分+线段树/树状数组)的更多相关文章
- P1438 无聊的数列 (差分+线段树)
题目 P1438 无聊的数列 解析: 先考虑修改,用差分的基本思想,左端点加上首项\(k\),修改区间\((l,r]\)内每个数的差分数组都加上公差\(d\),最后的\(r+1\)再减去\(k+(r- ...
- LUOGU P1438 无聊的数列 (差分+线段树)
传送门 解题思路 区间加等差数列+单点询问,用差分+线段树解决,线段树里维护的就是差分数组,区间加等差数列相当于在差分序列中l位置处+首项的值,r+1位置处-末项的值,中间加公差的值,然后单点询问就相 ...
- 洛谷P1438 无聊的数列 [zkw线段树]
题目传送门 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个数列{a[i]} ...
- 洛谷P1438 无聊的数列 (线段树+差分)
变了个花样,在l~r区间加上一个等差数列,等差数列的显著特点就是公差d,我们容易想到用线段树维护差分数组,在l位置加上k,在l+1~r位置加上d,最后在r+1位置减去k+(l-r)*d,这样就是在差分 ...
- CodeForces -163E :e-Government (AC自动机+DFS序+树状数组)
The best programmers of Embezzland compete to develop a part of the project called "e-Governmen ...
- 线段树+差分【p1438】无聊的数列
Description 维护一个数列{a[i]},支持两种操作: 1.1 L R K D:给出一个长度等于R-L+1的等差数列,首项为K,公差为D,并将它对应加到a[L]~a[R]的每一个数上.即:令 ...
- BZOJ_4636_蒟蒻的数列_线段树+动态开点
BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...
- 【bzoj5028】小Z的加油店 扩展裴蜀定理+差分+线段树
题目描述 给出 $n$ 个瓶子和无限的水,每个瓶子有一定的容量.每次你可以将一个瓶子装满水,或将A瓶子内的水倒入B瓶子中直到A倒空或B倒满.$m$ 次操作,每次给 $[l,r]$ 内的瓶子容量增加 $ ...
- COGS 2638. 数列操作ψ 线段树
传送门 : COGS 2638. 数列操作ψ 线段树 这道题让我们维护区间最大值,以及维护区间and,or一个数 我们考虑用线段树进行维护,这时候我们就要用到吉司机线段树啦 QAQ 由于发现若干次an ...
随机推荐
- lvarchar类型对表结构变更影响
informix中lvarchar类型设计用于存储中度长度的字符数据(短的常用varchar类型.特别长的字符可用text类型).其默认长度2048byte,最大长度32739byte,是一种可变长度 ...
- UOJ#55. 【WC2014】紫荆花之恋
传送门 暴力思路就是每次点分治计算答案 点分治之后,条件可以变成 \(dis_i-r_i\le r_j-dis_j\) 每次只要查找 \(r_j-dis_j\) 的排名然后插入 \(dis_j-r_j ...
- JavaScript 工具库:Cloudgamer JavaScript Library v0.1 发布
JavaScript 工具库:Cloudgamer JavaScript Library v0.1 发布 研究了一年多的js,也差不多写一个自己的js库了.我写这个不算框架,只是一个小型的js工具 ...
- Web前端面试指导(十八):用纯CSS创建一个三角形的原理是什么?
题目点评 三角形的图标在网页设计是很常见的,属于基本常识题,只要在练习做到过这个功能都能回答出来,可以把你做过的思路描述出来就可以了,本题的难易程度为简单 答题要点 1.采用的是均分原理 盒子都是一个 ...
- Node.js 常用 API
Node.js v6.11.2 Documentation(官方文档) Buffer Prior to the introduction of TypedArray in ECMAScript 20 ...
- 从零学React Native之04自定义对话框
本篇主要介绍: 1. 自定义组件 2. Alert 对话框 自定义对话框 之前的我都是利用React Native提供的基础组件对它们进行排列组合, 其实自定义也很简单, 我们还是拿上一篇文章的例子进 ...
- 比较和排序(IComparable和IComparer以及它们的泛型实现)(转)
C#笔记25:比较和排序(IComparable和IComparer以及它们的泛型实现) 本文摘要: 1:比较和排序的概念: 2:IComparable和IComparer: 3:IComparabl ...
- asp.net mvc4 小问题
最近在学习mvc4中间出现一些问题.留作记录.. 1.新建立的项目在vs2013中运行后会出现一个长轮询..这个叫browserLink 是vs2013中新加入的东西.至于更多解释.直接百度.. 关闭 ...
- course & time
- SSM框架——实现分页和搜索分页
登录|注册 在路上 在路上,要懂得积累:在路上,要学会放下:我在路上!Stay hungry,Stay foolish. 目录视图 摘要视图 订阅 [公告]博客系统优化升级 ...