无聊的数列

题目链接

无聊的序列

题目大意

给某个区间加上等差数列

解析

给原序列差分
然后加的操作只需要
(l) 出加上 (k)
([l+1,r]) 处加上 (d)
(r+1) 出加上 (-[k+d*(r-l)]) 消去影响
查询及查 ([1,p]) 的和

(Code)

#include<cstdio>
#define LL long long
#define ls (k << 1)
#define rs (ls | 1)
using namespace std;

const int N = 1e5 + 5;
int n , m , a[N];
struct segment{
	LL sum , tag;
}seg[N << 2];

void pushup(int k){seg[k].sum = seg[ls].sum + seg[rs].sum;}

void pushdown(int l , int r , int k)
{
	if (seg[k].tag == 0) return;
	int mid = (l + r) >> 1;
	seg[ls].sum += 1LL * (mid - l + 1) * seg[k].tag;
	seg[rs].sum += 1LL * (r - mid) * seg[k].tag;
	seg[ls].tag += seg[k].tag , seg[rs].tag += seg[k].tag;
	seg[k].tag = 0;
}

void build(int l , int r , int k)
{
	if (l == r)
	{
		seg[k].sum = a[l] - a[l - 1] , seg[k].tag = 0;
		return;
	}
	int mid = (l + r) >> 1;
	build(l , mid , ls) , build(mid + 1 , r , rs);
	pushup(k);
}

void update(int l , int r , int k , int tl , int tr , int v)
{
	if (tl > r || tr < l) return;
	if (tl <= l && r <= tr)
	{
		seg[k].sum += 1LL * (r - l + 1) * v , seg[k].tag += v;
		return;
	}
	pushdown(l , r , k);
	int mid = (l + r) >> 1;
	if (tl <= mid) update(l , mid , ls , tl , tr , v);
	if (tr > mid) update(mid + 1 , r , rs , tl , tr , v);
	pushup(k);
}

LL query(int l , int r , int k , int tl , int tr)
{
	if (tl <= l && r <= tr) return seg[k].sum;
	pushdown(l , r , k);
	int mid = (l + r) >> 1; LL res = 0;
	if (tl <= mid) res += query(l , mid , ls , tl , tr);
	if (tr > mid) res += query(mid + 1 , r , rs , tl , tr);
	return res;
} 

int main()
{
	scanf("%d%d" , &n , &m);
	for(register int i = 1; i <= n; i++) scanf("%d" , &a[i]);
	build(1 , n , 1);
	int op , l , r , k , d;
	while (m--)
	{
		scanf("%d" , &op);
		if (op == 2) scanf("%d" , &k) , printf("%lld
" , query(1 , n , 1 , 1 , k));
		else {
			scanf("%d%d%d%d" , &l , &r , &k , &d);
			update(1 , n , 1 , l , l , k);
			update(1 , n , 1 , l + 1 , r , d);
			update(1 , n , 1 , r + 1 , r + 1 , -(k + 1LL * d * (r - l)));
		}
	} 
}
原文地址:https://www.cnblogs.com/leiyuanze/p/14005037.html