維護乙個數列,支援兩種操作:
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]。
這道題很顯然可以用線段樹來做。
但這道題的區間修改是加上乙個等差數列,所以直接硬搞的話會比較困難,需要尋找其他的方法。
這時就很容易能就想到差分了。因為等差數列滿足an=an-1+d,它們的差不變,所以用差分來做會十分簡單。
我們可以將修改分為3部分。
1.對於區間左端點l:
s um
[l]=
sum[
l]+k
sum[l]=sum[l]+k
sum[l]
=sum
[l]+
k2.對於區間的中間部分l+1~r:
s um
[i]=
sum[
i−1]
+d,i
∈(l,
r]
sum[i]=sum[i-1]+d,i\in(l,r]
sum[i]
=sum
[i−1
]+d,
i∈(l
,r]3.對於區間右端點右邊一位r+1:
s um
[r+1
]=su
m[r+
1]−(
k+(r
−l)∗
d)
)sum[r+1]=sum[r+1]-(k+(r-l)*d))
sum[r+
1]=s
um[r
+1]−
(k+(
r−l)
∗d))
對於每次詢問第p個位置的值,答案即為
a [p
]+∑i
=1ps
um[i
]a[p]+\sum_^p sum[i]
a[p]+i
=1∑p
sum
[i]總結一下,就是要我們對差分陣列進行區間修改+區間求值。
這道題在修改的時候要特判兩種情況
1.l=r
這種情況不需要對上述三種中區間的中間部分進行修改。因為此時l+1>r,會越界
2.r=n
這種情況不需要對上述三種中區間右端點右邊一位進行修改。因為此時r+1>n,也會越界
#include#define maxn 100009
using namespace std;
int n,m,a[maxn];
struct node
tr[maxn*5];
void build_tree (int x,int l,int r)
void release (int x)
}void modify (int x,int l,int r,int d)
int mid=(tr[x].l+tr[x].r)>>1,ls=x<<1,rs=(x<<1)+1;
if (l<=mid)
modify(ls,l,r,d);
if (r>=mid+1)
modify(rs,l,r,d);
tr[x].sum=tr[ls].sum+tr[rs].sum;
}long long query (int x,int l,int r)
int main ()
if (op==2)
}return 0;
}
這道題一開始我居然傻傻地想要直接修改,虧最後還是轉過彎來了。太長時間不寫,第一次交了後才發現陣列開小了。真的菜啊qaq 洛谷 P1438 無聊的數列
題目背景 無聊的yyb總喜歡搞出一些正常人無法搞出的東西。有一天,無聊的yyb想出了一道無聊的題 無聊的數列。k峰 這題不是傻x題嗎 題目描述 維護乙個數列,支援兩種操作 1 1 l r k d 給出乙個長度等於r l 1的等差數列,首項為k,公差為d,並將它對應加到a l a r 的每乙個數上。即...
洛谷 P1438 無聊的數列
1 多次對於區間加上乙個等差數列,引數為l,r,k,d,表示首項為k,公差為d,將乙個長度r l 1的等差數列加到區間l.r上 2 詢問乙個值a i 要加上乙個等差數列,很容易想到差分,因此將題目簡化至下 1 將a l 加上k 2 將a l 1.r 加上d 3 將a r 1 r l d k 而查詢的...
洛谷 P1438 無聊的數列
p1438 無聊的數列 題目背景 無聊的yyb總喜歡搞出一些正常人無法搞出的東西。有一天,無聊的yyb想出了一道無聊的題 無聊的數列。k峰 這題不是傻x題嗎 題目描述 維護乙個數列,支援兩種操作 1 1 l r k d 給出乙個長度等於r l 1的等差數列,首項為k,公差為d,並將它對應加到a l ...