【洛谷】【线段树】P1438 无聊的数列

题目背景

无聊的YYB总喜欢搞出一些正常人无法搞出的东西。有一天,无聊的YYB想出了一道无聊的题:无聊的数列。。。(K峰:这题不是傻X题吗)

题目描述

维护一个数列{a[i]},支持两种操作:

1、1 L R K D:给出一个长度等于R-L+1的等差数列,首项为K,公差为D,并将它对应加到a[L]~a[R]的每一个数上。即:令a[L]=a[L]+K,a[L+1]=a[L+1]+K+D,

a[L+2]=a[L+2]+K+2D……a[R]=a[R]+K+(R-L)D。

2、2 P:询问序列的第P个数的值a[P]。

输入输出格式

输入格式:

第一行  两个整数数n,m,表示数列长度和操作个数。

第二行  n个整数,第i个数表示a[i](i=1,2,3…,n)。

接下来的m行,表示m个操作,有两种形式:

1 L R K D

2 P 字母意义见描述(L≤R)。


输出格式:

 

对于每个询问,输出答案,每个答案占一行。


输入输出样例

输入样例#1: 

5 2
1 2 3 4 5
1 2 4 1 2
2 3

输出样例#1: 

6

说明

数据规模:

0≤n,m≤100000

|a[i]|,|K|,|D|≤200


【题意】:

这个题目就是  区域更新+单点询问。但是这个区域更新是按照等差数列来更新的。

【题解】:

第一次写线段树的题解,我认为这个博客很有必要写,中石油做的那个题一样,这个题目维护的就是a[i],a[i] = 第i个元素 和 第(i-1)个元素 的差值,然后如果想表示第i个值,那么就是  [1,i] 区间求和得到。

这样就是维护一个差分数组即可,

区间更新:[L,R] 相当于 update( L, L, 首相) + update (L+1,R,公差) + update( R+1,R+1,首相+(len-1)*公差) 

区域更新需要写 pushdown + Add ()

但是这个题目有两个小坑,

1、L==R

2、R+1 == n

只要加以特判就不用更新这两个位置了。

#include 
using namespace std;
typedef long long ll;
const int N=1e6+1010;
ll a[N<<2],lazy[N<<2],b[N<<2],n,m;void Add(int No,int L,int R,ll w){lazy[No]+=w;a[No]+=(R-L+1ll)*w;return ;
}void pushdown(int No,int L,int R){if(lazy[No]==0) return;int Mid=(L+R)>>1;Add(No*2,L,Mid,lazy[No]);Add(No*2+1,Mid+1,R,lazy[No]);lazy[No]=0;
}void update(int No,int L,int R,int x,int y,ll v){if( y>1;if( x<=Mid)update(No*2,L,Mid,x,y,v);if( Mid>1;ll res = 0;if( x<= Mid) res+=query(No<<1,L,Mid,x,y);if( Mid>1;Build(No*2,L,Mid);Build(No*2+1,Mid+1,R);a[No] = a[No*2] + a[No*2+1];
}int main(){scanf("%lld%lld",&n,&m);memset(a,0,sizeof(a));memset(lazy,0,sizeof(lazy));for(int i=1; i<=n; i++)scanf("%lld",&b[i]);for(int i=n; i>=1; i--)b[i] = b[i] - b[i-1];Build(1,1,n);ll D,d,S,len,R,L,ins;while(m--){scanf("%lld",&ins);if(ins==1){scanf("%lld%lld%lld%lld",&L,&R,&D,&d);len = (R-L+1ll);update(1,1,n,L,L,D);if( L

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部