題意:乙個多重集合的價值為將其變為公差為d
dd(將在第一行輸入)的等差數列需要插入幾個數字(無法實現價值為0)。多次詢問l,r
l,rl,
r,求[l,
r]
[l,r]
[l,r
]的子區間的價值和。
序列長度3e5
3e53e
5,數字大小和d≤1
e7
d\leq 1e7
d≤1e7
首先對於r
′>
rr'>r
r′>r,l
ll使得[l,
r]
[l,r]
[l,r
]是最長的可以實現的區間,l′l'
l′是使得[l′
,r′]
[l',r']
[l′,r′
]是最長的可以實現的區間,那麼l′≥
ll' \geq l
l′≥l
,所以我們可以用雙指標掃一遍求出所有可以實現的區間在哪些區間內。
那麼對於所有可以實現的區間,我們有乙個簡單的方法可以計算乙個區間[l,
r]
[l,r]
[l,r
]構成的集合的價值:
最 大值
d−最小
值d+l
−r
\frac d - \frac d + l - r
d最大值−
d最小值
+l−
r l,
r]
[l,r]
[l,r
]的價值,離線後就是雙指標右端點到達r
rr時,單點查詢lll.
如果問的是∑i=
lr[i
,r
]\sum_^r [i,r]
∑i=lr
[i,r
]的價值,那麼就是區間查詢l,r
l,rl,
r可是我們詢問的是∑i=
lr∑j
=ir[
i,j]
\sum_^r \sum_^r [i,j]
∑i=lr
∑j=i
r[i
,j]的價值和。
這就意味著我們在右端點是r
rr的時候還需要統計到右端點是r
−1...
r-1...
r−1...
的答案。
所以我們假設右端點在i
ii的時候就是我們線段樹的第i
ii個版本。
那麼我們相當於就是要求線段樹的歷史版本區間和hsu
mhsum
hsum
。需要增加乙個標記tag
tagta
g,這個標記的意義是:
當乙個區間打上tag
+=
vtag += v
tag+=v
時,h su
m+=s
um∗v
hsum += sum * v
hsum+=
sum∗
v。然後在之後下放給兒子。
考慮這個標記會和區間加add
addad
d標記有不良互動。於是我們讓乙個區間在同時有add
addad
d和ta
gtag
tag時先下放add
addad
d再下放tag
tagta
g。那麼在乙個有add
addad
d的點上打tag
tagta
g不會影響先後順序,沒有問題。但是反過來在有tag
tagta
g的點上打add
addad
d後下放這個點的標記就會造成前後顛倒。
那麼就把多加的hsu
mhsum
hsum
減回去,新加乙個標記add
haddh
addh
,當乙個區間打上add
h+=v
addh+= v
addh+=
v時,hsu
m+=l
en∗v
hsum += len * v
hsum+=
len∗
v。然後在之後下放給兒子,這裡的len是這個區間的長度。
那麼就結束了。
a cc
od
e\rm ac \ code
accode
#include
#define maxn 300005
#define f first
#define s second
#define mp make_pair
#define pii pair
#define ll long long
#define lc u<<1
#define rc lc|1
using
namespace std;
int n,d,q,s[maxn]
;vectorg[maxn]
;ll sm[maxn<<3]
,hsm[maxn<<3]
,ad[maxn<<3]
,adh[maxn<<3]
,len[maxn<<3]
,had[maxn<<3]
;void
dtp2
(int u,
int v)
void
dtp3
(int u,ll v,
int t=1)
void
dtp1
(int u,
int v)
voiddt(
int u)
void
add(
int u,
int l,
int r,
int ql,
int qr,
int v)
void
pud(
int u,
int l,
int r,
int ql,
int qr)
ll qry
(int u,
int l,
int r,
int ql,
int qr)
void
build
(int u,
int l,
int r)
int st[2]
[maxn]
,qr[2]
;int cd[
10000007
],scd,usd[
10000007
],sud;
ll ans[maxn]
;int
main()
build(1
,1,n);
for(
int i=
1,j=
1;i<=n;i++
)for
(int i=
1;i<=q;i++
)printf
("%lld\n"
,ans[i]);
}
線段樹 維護序列
老師交給小可可乙個維護數列的任務,現在小可可希望你來幫他完成。有長為 n 的數列,不妨設為 a1,a2,an。有如下三種操作形式 把數列中的一段數全部乘乙個值 把數列中的一段數全部加乙個值 詢問數列中的一段數的和,由於答案可能很大,你只需輸出這個數模 p 的值。輸入格式 第一行兩個整數 n 和 p ...
線段樹 GD SGOI 公路維護
用線段樹維護區間沒有被損壞的路的最小值,最小值對應的下標,區間被損壞的路的個數。標記下穿的時候先傳add,再傳mark,傳add的時候minv,add,mark都要加上add o 傳mark的時候,minv,mark都要取最大。include include include include incl...
線段樹 I 維護序列
老師交給小可可乙個維護數列的任務,現在小可可希望你來幫他完成。有長為 nn 的數列,不妨設為 a1,a2,ana1,a2,an。有如下三種操作形式 input 第一行兩個整數 nn 和 pp 第二行含有 nn 個非負整數,從左到右依次為 a1,a2,ana1,a2,an 第三行有乙個整數 mm,表示...