洛谷P1438 无聊的数列

洛谷P1438 无聊的数列

题目描述

维护一个数列 \({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) \times 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 \leq R)\)

输出格式:

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

思路

线段度区间维护
首先,根据等差数列,我们可以想到差分
用线段树维护一个原数列的差分数列
\([x,y]\)加一个\(a\)为首项,\(d\)为公差的等差数列的操作就可以分为以下三个操作

  1. 在差分数列的第\(x\)项加\(a\)
  2. 在差分数列的第\([x+1,y]\)项区间整体加上\(d\)
  3. 在差分数列的第\(y+1\)项减去\(a+d(y-x)\)

Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 100010
struct T{
	int l,r,val,addval;
	T(){}
}tr[MAXN<<2];
int nums[MAXN];
int i,j,k,m,n,x,y,a,d;
char readc;
short signal;
void read(int &n){
	signal=1;
	while((readc=getchar())<48||readc>57) if(readc=='-') signal=-1;
	n=readc-48;
	while((readc=getchar())>=48&&readc<=57) n=n*10+readc-48;
	n*=signal;
}
void build(int r,int s,int e){
	if(s==e){
		tr[r].l=tr[r].r=s;
		tr[r].val=nums[s];
		tr[r].addval=0;
		return;
	}
	tr[r].l=s,tr[r].r=e;
	tr[r].addval=0;
	int mid=(s+e)>>1;
	build(r<<1,s,mid),build((r<<1)+1,mid+1,e);
	tr[r].val=tr[r<<1].val+tr[(r<<1)+1].val;
}
void pushdown(int r){
	if(tr[r].addval){
		tr[r<<1].val+=tr[r].addval*(tr[r<<1].r-tr[r<<1].l+1),tr[(r<<1)+1].val+=tr[r].addval*(tr[(r<<1)+1].r-tr[(r<<1)+1].l+1);
		tr[r<<1].addval+=tr[r].addval,tr[(r<<1)+1].addval+=tr[r].addval;
		tr[r].addval=0;
	}
}
void update(int r,int us,int ue,int ns,int ne,int addval){
	if(ne<us||ns>ue) return;
	if(us<=ns&&ue>=ne){
		tr[r].val+=addval*(tr[r].r-tr[r].l+1);
		tr[r].addval+=addval;
		return;
	}
	pushdown(r);
	int mid=(ns+ne)>>1;
	update(r<<1,us,ue,ns,mid,addval);
	update((r<<1)+1,us,ue,mid+1,ne,addval);
	tr[r].val=tr[r<<1].val+tr[(r<<1)+1].val;
}
int query(int r,int qs,int qe,int ns,int ne){
	if(ns>qe||ne<qs) return 0;
	if(qs<=ns&&qe>=ne) return tr[r].val;
	pushdown(r);
	int mid=(ns+ne)>>1;
	return query(r<<1,qs,qe,ns,mid)+query((r<<1)+1,qs,qe,mid+1,ne);
}
int main(){
#ifndef ONLINE_JUDGE
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);
#endif
	read(n),read(m);
	for(i=1;i<=n;i++) read(nums[i]);
	for(i=n;i>=1;i--) nums[i]=nums[i]-nums[i-1];
	build(1,1,n);
	for(i=1;i<=m;i++){
		read(k);
		if(k==1){
			read(x),read(y),read(a),read(d);
			update(1,x,x,1,n,a);
			if(x+1<=y) update(1,x+1,y,1,n,d);
			if(y+1<=n) update(1,y+1,y+1,1,n,-(a+d*(y-x)));
		}else{
			read(x);
			printf("%d\n",query(1,1,x,1,n));
		}
	}
	return 0;
}
posted @ 2019-01-16 22:06  EternalBlue  阅读(171)  评论(0编辑  收藏  举报