P1438 无聊的数列(差分&线段树)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1438 无聊的数列(差分&线段树)相关的知识,希望对你有一定的参考价值。

P1438 无聊的数列(差分&线段树)

区间加上等差数列,可以利用等差数列的差分数组相同的性质来做。

对于 [ L , R ] [L,R] [L,R]加上一个等差数列。

如:

原始区间: [ 0 , 0 , 0 , 0 , 0 , 0 ] [0,0,0,0,0,0] [0,0,0,0,0,0]

区间 [ 1 , 5 ] [1,5] [1,5]加上 [ 1 , 3 , 5 , 7 , 9 , 0 ] [1,3,5,7,9,0] [1,3,5,7,9,0]

[ 1 , 3 , 5 , 7 , 9 , 0 ] [1,3,5,7,9,0] [1,3,5,7,9,0]

差分数组变为: [ 1 , 2 , 2 , 2 , 2 , − 9 ] [1,2,2,2,2,-9] [1,2,2,2,2,9]

即: a [ L ] + = k a[L]+=k a[L]+=k [ L + 1 , R ] [L+1,R] [L+1,R]都加上 d d d

a [ R + 1 ] − = ( k + ( R − L ) × d ) a[R+1]-=(k+(R-L)\\times d) a[R+1]=(k+(RL)×d)

然后就是裸的区间修改,区间求和。

code

// Problem: P1438 无聊的数列
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1438
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-07-06 17:00:40
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
//if have char input #define should cancel
#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
template <typename T>
inline T& read(T& r) {
    r = 0; bool w = 0; char ch = getchar();
    while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
    while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
    return r = w ? -r : r;
}
int n,m;
struct node{
	int l,r;
	int lz,s;
}a[N<<2];
#define lx x<<1
#define rx x<<1|1
int b[N];
void re(int x){
	a[x].s=a[lx].s+a[rx].s;
}
void bud(int x,int l,int r){
	a[x].l=l,a[x].r=r,a[x].s=0;
	if(l==r){
		a[x].s=b[l];return;
	}
	int mid=l+r>>1;
	bud(lx,l,mid),bud(rx,mid+1,r);
	re(x);
}
void pushdown(int x){
	if(a[x].lz){
		a[lx].lz+=a[x].lz,a[rx].lz+=a[x].lz;
		a[lx].s+=(a[lx].r-a[lx].l+1)*a[x].lz;
		a[rx].s+=(a[rx].r-a[rx].l+1)*a[x].lz;
		a[x].lz=0;
	}
}
void upd(int x,int l,int r,int v){
	if(a[x].l>=l&&a[x].r<=r){
		a[x].lz+=v;
		a[x].s+=(a[x].r-a[x].l+1)*v;return;
	}
	pushdown(x);
	int mid=a[x].l+a[x].r>>1;
	if(l<=mid) upd(lx,l,r,v);
	if(r>mid) upd(rx,l,r,v);
	re(x);
}
int que(int x,int l,int r){
	if(a[x].l>=l&&a[x].r<=r) return a[x].s;
	pushdown(x);
	int s=0;
	int mid=a[x].l+a[x].r>>1;
	if(l<=mid) s+=que(lx,l,r);
	if(r>mid) s+=que(rx,l,r);
	return s;
}
int main(){
	read(n),read(m);
	for(int i=1;i<=n;i++) read(b[i]);
	for(int i=n;i;i--) b[i]=b[i]-b[i-1];
	bud(1,1,n);
	while(m--){
		int op,l,r,d,k;
		read(op);
		if(op==1){
			read(l),read(r),read(k),read(d);
			upd(1,l,l,k);
			if(l+1<=r) upd(1,l+1,r,d);
			if(r<n) upd(1,r+1,r+1,-(k+(r-l)*d));
		}
		else {
			int x;read(x);
			printf("%d\\n",que(1,1,x));
		}
	}
	return 0;
}

以上是关于P1438 无聊的数列(差分&线段树)的主要内容,如果未能解决你的问题,请参考以下文章

P1438 无聊的数列

[Luogu] P1438 无聊的数列 | 线段树简单题

P1438 无聊的数列

[LuoguP1438]无聊的数列(差分+线段树/树状数组)

P1438 无聊的数列

[luogu P1438] 无聊的数列