洛谷 P1438 无聊的数列

2024-06-04 09:28
文章标签 数列 洛谷 无聊 p1438

本文主要是介绍洛谷 P1438 无聊的数列,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意

给定一个序列 A = ( A 1 , A 2 , ⋯ , A n ) A=(A_1,A_2,\cdots,A_n) A=(A1,A2,,An)
现在进行 m m m次操作,分为以下两种:

  • 1 l r k d:给定一个长度为 r − l + 1 r-l+1 rl+1的等差序列,首项为 k k k,公差为 d d d,并将它对应加到 [ l , r ] [l,r] [l,r]范围中的每一个数上。
  • 2 x:查询 A x A_x Ax的值。

思路

将序列 A A A进行差分,记差分数组为 B B B
接下来,如果要加上一个等差序列,则要进行以下操作:

  • B l = B l + k B_l=B_l+k Bl=Bl+k
  • B i = B i + d ( i ∈ [ l , r ] ) B_i=B_i+d \quad (i \in [l, r]) Bi=Bi+d(i[l,r])
  • B r + 1 = B r + 1 − ( k + d × ( r − l ) ) B_{r+1}=B_{r+1}-(k + d \times (r - l)) Br+1=Br+1(k+d×(rl))

如果不懂,看看下面的例子:
原序列:  A = ( 0 , 0 , 0 , 0 , 0 , 0 ) A=(0,0,0,0,0,0) A=(0,0,0,0,0,0)
差分序列: B = ( 0 , 0 , 0 , 0 , 0 , 0 ) B=(0,0,0,0,0,0) B=(0,0,0,0,0,0)
等差序列: C = ( 1 , 3 , 5 , 7 , 9 ) C=(1,3,5,7,9) C=(1,3,5,7,9)
现序列:  A = ( 1 , 3 , 5 , 7 , 9 , 0 ) A=(1,3,5,7,9,0) A=(1,3,5,7,9,0)
差分序列: B = ( 1 , 2 , 2 , 2 , 2 , − 9 ) B=(1,2,2,2,2,-9) B=(1,2,2,2,2,9)

如果要查询 A p A_p Ap,就输出 ∑ i = 1 p B i \sum_{i=1}^{p} B_i i=1pBi
执行以上操作,只需要一个支持单点修改、区间修改。区间查询的线段树即可。

代码

#include <iostream>
#include <vector>
using namespace std;#define int long longstruct segment{#define ls (u << 1)#define rs (u << 1 | 1)struct Node{int l, r, sum = 0, add = 0;};vector<Node> tr;segment(vector<int> &a){int n = a.size();tr.resize(n << 2);build(1, 1, n, a);}void pushup(int u){tr[u].sum = tr[ls].sum + tr[rs].sum;;}void build(int u, int l, int r, vector<int> &a){tr[u].l = l; tr[u].r = r;if(l == r){tr[u].sum = a[l - 1];return;}int mid = l + r >> 1;build(ls, l, mid, a);build(rs, mid + 1, r, a);pushup(u);} void pushdown(int u){if(tr[u].add){tr[ls].sum += tr[u].add * (tr[ls].r - tr[ls].l + 1);tr[rs].sum += tr[u].add * (tr[rs].r - tr[rs].l + 1);tr[ls].add += tr[u].add;tr[rs].add += tr[u].add;tr[u].add = 0;}}void modify(int u, int l, int r, int v){if(l <= tr[u].l && tr[u].r <= r){tr[u].sum += v * (tr[u].r - tr[u].l + 1);tr[u].add += v;return;}pushdown(u);int mid = tr[u].l + tr[u].r >> 1;if(l <= mid) modify(ls, l, r, v);if(r > mid) modify(rs, l, r, v);pushup(u);}int query(int u, int l, int r){if(l <= tr[u].l && tr[u].r <= r) return tr[u].sum;pushdown(u);int mid = tr[u].l + tr[u].r >> 1;int ans = 0;if(l <= mid) ans += query(ls, l, r);if(r > mid) ans += query(rs, l, r);return ans;}#undef ls#undef rs
};signed main(){ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int n, m;cin >> n >> m;vector<int> a(n);for(auto &i: a) cin >> i;vector<int> diff(n);diff[0] = a[0];for(int i = 1; i < n; i++) diff[i] = a[i] - a[i - 1]; segment seg(diff);for(int i = 0; i < m; i++){int op;cin >> op;if(op == 1){int l, r, k, d;cin >> l >> r >> k >> d;seg.modify(1, l, l, k);if(l + 1 <= r) seg.modify(1, l + 1, r, d);if(r < n) seg.modify(1, r + 1, r + 1, -(k + d * (r - l)));}else{int p;cin >> p;cout << seg.query(1, 1, p) << endl;}}return 0;
}

这篇关于洛谷 P1438 无聊的数列的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1029688

相关文章

高精度计算(代码加解析,洛谷p1601,p1303)除法待更新

目录 高精度加法 高精度减法 高精度乘法 高精度加法 我们知道在c++语言中任何数据类型都有一定的表示范围。当两个被加数很大时,正常加法不能得到精确解。在小学,我们做加法都采用竖式方法。那么我们也只需要按照加法进位的方式就能得到最终解。 8 5 6+ 2 5 5-------1 1 1 1 加法进位: c[i] = a[i] + b[i];if(c[i] >=

UVa 10820 Send a Table (Farey数列欧拉函数求和)

这里先说一下欧拉函数的求法 先说一下筛选素数的方法 void Get_Prime(){ /*筛选素数法*/for(int i = 0; i < N; i++) vis[i] = 1;vis[0] = vis[1] = 0;for(int i = 2; i * i < N; i++)if(vis[i]){for(int j = i * i; j < N; j += i)vis[j] =

洛谷 凸多边形划分

T282062 凸多边形的划分 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 先整一个半成品,高精度过两天复习一下补上 #include <iostream>#include <algorithm>#include <set>#include <cstring>#include <string>#include <vector>#include <map>

能量项链,洛谷

解释:  环形dp问题还是考虑将环拉直,可以参考我上一篇文章:环形石子合并 [2 3 5 10 2] 3 5 10 将环拉直,[]内是一个有效的区间,可以模拟吸收珠子的过程,         如[2 3 5] <=>(2,3)(3,5)    2是头,3是中间,5是尾 len >= 3:因为最后[2 10 2]是最小的可以合并的有效区间 len <= n + 1因为[2 3

【练习7】Fibonacci数列

链接:https://www.nowcoder.com/practice/18ecd0ecf5ef4fe9ba3f17f8d00d2d66 分析: 当n为15的时候,可以用Math.min(c-n,n-b)来判断哪个是变成斐波那契数的最小步数。 public class Main {public static void main(String[] args) {Scanner i

牛客《剑指Offer》 -- 斐波那契数列

题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。 n<=39 思路 对于n=0,应返回0。 class Solution {public:int Fibonacci(int n) {if(n==0) return 0;if(n==1||n==2) return 1;int a=1,b=1,c;n= n-2;for(int i =0

面试题41:和为s的两个数VS和为s的连续正数数列

问题说明: 1.和为s的两个数问题是从一个排序的数组中找出和为s的两个数; 2.原题是找出一个即可,现在全部找出; 3.和为s的连续正数数列是给定一个数找出所有连续正数数列的和为s,例如s为9,(2,3,4)就是其中一组。 (一)和为s的两个数问题 public static int findNumbersWithSum(int[] sorted, int fromIndex, in

洛谷P5490扫描线

0是最小的数字,将一个线段看成一个区间,对于一个矩形,从下扫到上,入边为1,而出边为-1,意思是将这个区间上的所有点加1(区间修改).把线段表示为Line[i],其中记录了l,r,h,tag,左右端点,高度,入边还是出边(1或-1) 那么每次区间修改后不为0的区间它的值可能是1,2,3或者是其它数字,这不好统计,可以将它转化一下,0是不是表示没有被覆盖过的地方,我们只要统计0的个数然后用总长减去

挤牛奶洛谷uasco

题目描述 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒。第二个农民在700秒开始,在 1200秒结束。第三个农民在1500秒开始2100秒结束。期间最长的至少有一个农民在挤奶的连续时间为900秒(从300秒到1200秒),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300秒(从1200秒到1500秒)。

1037 计算数列和

### 思路 1. 初始化两个变量表示数列的前两项。 2. 使用循环计算数列的前 `n` 项,并累加每一项的值。 3. 输出累加的结果,保留四位小数。 ### 伪代码 1. 初始化 `a = 2.0`,`b = 1.0`,`sum = 0.0` 2. 循环 `n` 次:    - 计算当前项 `current = a / b`    - 将 `current` 加到 `sum`    - 更