給定乙個長度為n的原序列和模數mod,m個操作,[a,b]區間乘c,[a,b]區間加c,統計[a,b]的區間和。
思路
線段樹維護的還是區間和,但是這裡我們需要用到兩個懶標記,乙個記錄加法,乙個記錄乘法,乘法懶標記下傳之後要重置為1而不是0。對於乙個乘法操作,他影響的是區間和還有這個區間的加法標記、乘法標記。即如果原來這個區間的加法懶標記的值為1,然後傳來了乙個區間乘5的操作,那麼這個加法懶標記也要乘5。
#include
using
namespace std;
typedef
long
long ll;
const
int n=
1e6+5;
//const int mod=1e9+7;
const
int inf=
0x7fffffff
;const ll llinf=
0x7fffffffffffffff
;const
double eps=
1e-10
;#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define pb push_back
#define pii pair
#define pll pair
#define debug cout<<"debug"<#define ls p<<1
#define rs p<<1|1
#define int long long
int a[n]
;int n,mod;
struct tree
t[n<<2]
;void
build
(int p,
int x,
int y)
int mid=x+y>>1;
build
(ls,x,mid)
;build
(rs,mid+
1,y)
; t[p]
.pre=
(t[ls]
.pre%mod+t[rs]
.pre%mod)
%mod;
}void
spread
(int p)
void
change1
(int p,
int x,
int y,
int z)
spread
(p);
int mid=t[p]
.l+t[p]
.r>>1;
if(x<=mid)
change1
(ls,x,y,z);if
(y>mid)
change1
(rs,x,y,z)
; t[p]
.pre=
(t[ls]
.pre+t[rs]
.pre)
%mod;
}void
change2
(int p,
int x,
int y,
int z)
spread
(p);
int mid=t[p]
.l+t[p]
.r>>1;
if(x<=mid)
change2
(ls,x,y,z);if
(y>mid)
change2
(rs,x,y,z)
; t[p]
.pre=
(t[ls]
.pre+t[rs]
.pre)
%mod;
}int
ask(
int p,
int x,
int y)
spread
(p);
int mid=t[p]
.l+t[p]
.r>>1;
int ans=0;
if(x<=mid)
ans=
(ans+
ask(ls,x,y)
)%mod;
if(y>mid)
ans=
(ans+
ask(rs,x,y)
)%mod;
return ans%mod;
}signed
main()
build(1
,1,n);
int m;
scanf
("%lld"
,&m)
;while
(m--)if
(oo==2)
if(oo==3)
}}
線段樹 區間加乘區間最大
如題,已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數加上x 2.將某區間每乙個數乘上x 3.求出某區間每乙個數的和 第一行包含三個整數n m p,分別表示該數列數字的個數 操作的總個數和模數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3或4個...
線段樹維護區間01
g.小 w 開關燈 problem 4467 discussion description 晚上到家小 w 通過開關燈來保持自己神經的興奮以便清醒地理筆記。n n 2 n 100,000 2 n 100,000 盞燈被連續的編號為 1 n 1 n 剛回到家的時候,所有的燈都是關閉的。小w 通過 n ...
線段樹 離散區間,單點維護區間
這道題當時用線段樹搞不行,用主席樹搞,也不行。當場自閉。其實當時想到離散,但是沒想到用單點維護線段樹的區間。你這樣想,無非就是2e6次詢問,最多1 e9被分成最多2e6區間,我們要求的位置,一定在這2e6點的右邊第乙個。那麼把這個點,以及這個點x以及x 1的點儲存下來。維護的時候,線段樹初始化所有的...