Two operations, add a number to an interval, query the greatest common divisor of the interval, we know that for the line segment tree without lazy mark, only single-point modification and interval query can be done. If you want to query the interval, you must add lazy Mark, but we think about it carefully. There is only one interval modification operation in the question. Add a number to each number in a range. Is it very familiar? Yes, it is the difference.
We can use the difference array, we only need to modify the left and right endpoints of the interval to modify all the numbers in the interval. Set the b array as a difference array, and add a c to the original array interval [l,r] to become b[ l]+=c, b[r+1]+=c;
For the greatest common divisor of the query interval,We know that the greatest common divisor of an interval is gcd( al, al+1, al+2 ,... ar), but now it is the difference, we can transform it into gcd(al, al+1-al, al +2 -al+1 ,…ar-ar-1)(I don’t know the nature of Baidu on my own ), then the greatest common divisor of an interval is gcd(al) ,gcd(al+1-al, al +2-al+1 ,…ar-ar-1) these two Partial composition, for the first part, al = b1+b2 +b3 +…+ bl (the sum of the sum difference array interval must be present in the node of the line segment tree) For the second part, the interval difference array is a gcd
Code
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<algorithm>usingnamespace std;typedeflonglong ll;constint N =5e5+10;int n, m;
ll w[N];struct Node {
ll l, r;
ll sum;
ll d;} tr[N *4];
ll gcd(ll a, ll b){
return b ?gcd(b, a % b): a;}voidpushup(Node &u, Node &l, Node &r){
u.sum = l.sum + r.sum;
u.d =gcd(l.d, r.d);}voidpushup(ll u){
pushup(tr[u], tr[u <<1], tr[u <<1|1]);}voidbuild(ll u, ll l, ll r){
if(l == r){
ll b = w[l]- w[l -1];
tr[u]={
l, r, b, b};}else{
tr[u]={
l, r};
ll mid =(l + r)>>1;build(u <<1, l, mid),build(u <<1|1, mid +1, r);pushup(u);}}voidmodify(ll u, ll x, ll v){
if(tr[u].l == x && tr[u].r == x){
ll b = tr[u].sum + v;
tr[u]={
x, x, b, b};}else{
ll mid =(tr[u].l + tr[u].r)>>1;if(x <= mid)modify(u <<1, x, v);elsemodify(u <<1|1, x, v);pushup(u);}}
Node query(ll u, ll l, ll r){
if(l <= tr[u].l && tr[u].r <= r)return tr[u];else{
ll mid =(tr[u].l + tr[u].r)>>1;if(r <= mid)returnquery(u <<1, l, r);elseif(l > mid)returnquery(u <<1|1, l, r);else{
Node res;auto left =query(u <<1, l, r);auto right =query(u <<1|1, l, r);pushup(res, left, right);return res;}}}intmain(){
cin >> n >> m;for(int i =1; i <= n; i++)scanf("%lld",&w[i]);build(1,1, n);while(m--){
string op;
ll l, r, d;
cin>>op;if(op =="C"){
cin >> l >> r >> d;modify(1, l, d);if(r +1<= n){
modify(1, r +1,-d);}}else{
cin >> l >> r;auto left =query(1,1, l);auto right =query(1, l +1, r);
cout <<abs(gcd(left.sum, right.d))<< endl;}}return0;}