区间最大公约数(线段树模板)

链接

  1 #include <bits/stdc++.h>
  2 #define go continue
  3 #define int long long
  4 #define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
  5 #define fory(i,a,b) for(int i = a; i <= b; ++i)
  6 using namespace std;
  7 
  8 template <typename T> inline void read(T& t) {
  9     int f = 0, c = getchar();
 10     t = 0;
 11     while (!isdigit(c)) f |= c == '-', c = getchar();
 12     while (isdigit(c)) t = t * 10 + c - 48, c = getchar();
 13     if (f) t = -t;
 14 }
 15 
 16 template <typename T> void print(T x) {
 17     if (x < 0) x = -x, putchar('-');
 18     if (x > 9) print(x / 10);
 19     putchar(x % 10 + 48);
 20 }
 21 
 22 const int N =  5e5 + 10;
 23 
 24 int n, m, a[N];
 25 
 26 inline int gcd(int a, int b) {
 27     return b ? gcd(b, a % b) : a;
 28 }
 29 
 30 struct node {
 31     int l, r, sum, d;
 32 };
 33 
 34 struct segment_tree {
 35 
 36     node t[N << 2];
 37     int mp[N];
 38 
 39     inline void help_push(node& a, node& b, node& c) {
 40         a.sum = b.sum + c.sum;
 41         a.d = gcd(b.d, c.d);
 42     }
 43 
 44     inline void push_up(int root) {
 45         int ch = root << 1;
 46         help_push(t[root], t[ch], t[ch + 1]);
 47     }
 48 
 49     inline void build(int root, int l, int r) {
 50         t[root].l = l;
 51         t[root].r = r;
 52         if(l != r) {
 53             int ch = root << 1;
 54             int mid = (l + r) >> 1;
 55             build(ch, l, mid);
 56             build(ch + 1, mid + 1, r);
 57             push_up(root);
 58         } else {
 59             int tmp = a[l] - a[l - 1];
 60             t[root].d = tmp;
 61             t[root].sum = tmp;
 62             mp[l] = root;
 63         }
 64     }
 65 
 66     inline void change(int root, int x, int y) {
 67         x = mp[x];
 68         t[x].d = t[x].sum + y;
 69         t[x].sum += y;
 70 
 71         while(x >>= 1) push_up(x);
 72     }
 73 
 74     inline node query(int root, int l, int r) {
 75         if(t[root].l >= l && t[root].r <= r) {
 76             return t[root];
 77         } else {
 78             int ch = root << 1;
 79             int mid = (t[root].l + t[root].r) >> 1;
 80 
 81             if(mid >= r) return query(ch, l, r);
 82             else if(l > mid) return query(ch + 1, l, r);
 83             else {
 84                 node left = query(ch, l, mid);
 85                 node right = query(ch + 1, mid + 1, r);
 86                 node res;
 87                 help_push(res, left, right);
 88                 return res;
 89             }
 90         }
 91     }
 92 
 93 } st;
 94 
 95 int l, r, x;
 96 char op[2];
 97 
 98 signed main() {
 99     read(n), read(m);
100     fory(i, 1, n) read(a[i]);
101 
102     st.build(1, 1, n);
103 
104     while(m--) {
105         scanf("%s%lld%lld", op, &l, &r);
106         if(*op == 'C') {
107             read(x);
108             st.change(1, l, x);
109             if(r + 1 <= n) st.change(1, r + 1, -x);
110         } else {
111             node ll = st.query(1, 1, l);
112             node rr = {0, 0, 0, 0};
113             if(l + 1 <= r) rr = st.query(1, l + 1, r);
114             printf("%lld\n", abs(gcd(ll.sum, rr.d)));
115         }
116     }
117     return 0;
118 }
119 /*
120 input:
121 5 5
122 1 3 5 7 9
123 Q 1 5
124 C 1 5 1
125 Q 1 5
126 C 3 3 6
127 Q 2 4
128 output:
129 1
130 2
131 4
132 
133 ps:
134 C l r d  修改操作 [l, r] + d
135 Q l r 询问操作 [l, r] 的区间GCD
136 */

 

posted @ 2022-04-06 17:34  std&ice  阅读(108)  评论(0编辑  收藏  举报