如題,已知乙個數列,你需要進行下面兩種操作:
1.將某區間每乙個數加上x
2.將某區間每乙個數乘上x
3.求出某區間每乙個數的和
第一行包含三個整數n、m、p,分別表示該數列數字的個數、操作的總個數和模數。
第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。
接下來m行每行包含3或4個整數,表示乙個操作,具體如下:
操作1: 格式:1 x y k 含義:將區間[x,y]內每個數乘上k
操作2: 格式:2 x y k 含義:將區間[x,y]內每個數加上k
操作3: 格式:3 x y 含義:輸出區間[x,y]內每個數的和對p取模所得的結果
輸出包含若干行整數,即為所有操作3的結果。
5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4 172
對於70%的資料:n<=1000,m<=10000
對於100%的資料:n<=100000,m<=100000
#includeusing namespace std;
#define lc (p<<1)
#define rc (p<<1|1)
long long n,m,a[100010],mod;
struct nodet[100010*4];
inline void pushup(long long p)
inline void pushadd(long long p,long long x)
inline void pushmul(long long p,long long x)
inline void pushdown(long long p)
if(t[p].add)
}inline void build(long long p,long long l,long long r)
long long mid=(l+r)>>1;
build(lc,l,mid);
build(rc,mid+1,r);
pushup(p);
}inline void add(long long p,long long l,long long r,long long x)
long long mid=(t[p].l+t[p].r)>>1;
pushdown(p);
if(l<=mid) add(lc,l,r,x);
if(r>mid) add(rc,l,r,x);
pushup(p);
}//區間加
inline void mul(long long p,long long l,long long r,long long x)
long long mid=(t[p].l+t[p].r)>>1;
pushdown(p);
if(l<=mid) mul(lc,l,r,x);
if(r>mid) mul(rc,l,r,x);
pushup(p);
}// 區間乘
inline long long query(long long p,long long l,long long r)
long long mid=(t[p].l+t[p].r)>>1,ans=0;
pushdown(p);
if(l<=mid) ans=(ans+query(lc,l,r))%mod;
if(r>mid) ans=(ans+query(rc,l,r))%mod;
pushup(p);
return ans;
}//區間求和
int main()
if(k==2)
if(k==3)
} return 0;
}
維護序列(線段樹維護區間乘 區間加)
給定乙個長度為n的原序列和模數mod,m個操作,a,b 區間乘c,a,b 區間加c,統計 a,b 的區間和。思路 線段樹維護的還是區間和,但是這裡我們需要用到兩個懶標記,乙個記錄加法,乙個記錄乘法,乘法懶標記下傳之後要重置為1而不是0。對於乙個乘法操作,他影響的是區間和還有這個區間的加法標記 乘法標...
線段樹 區間加區間乘
給出序列 a1,a2,an 0 ai 109 有關序列的四種操作 1.al,al 1,ar 1 l r n 加上 x 103 x 103 2.al,al 1,ar 1 l r n 乘上 x 103 x 103 3.al,al 1,ar 1 l r n 變成 x al,x al 1 x ar 103 ...
線段樹 二 區間乘 區間加
放 注意點 注意運算子優先順序 比如 a b p 是b先mod p再與a相乘 a 1 1是1 1再a位移 a 1 a 2 a 1 1 a 2 1 參見 線段樹v2.0 支援區間加 區間乘 區間和查詢 include include include define n 1000010 using nam...