题目链接
题目大意
给某个区间加上等差数列
解析
给原序列差分
然后加的操作只需要
在 (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)));
}
}
}