zoukankan      html  css  js  c++  java
  • 牛客-小阳的贝壳

    题目传送门

    sol:题目读完就知道是线段树,gcd满足结合律。操作2也好想到差分,但是不会修改后维护gcd。看了题解发现还是差分,这个差分用的妙啊;

    • 线段树+差分
      #include "bits/stdc++.h"
      using namespace std;
      const int MAXN = 1e5 + 10;
      struct Tree{
          int l, r;
          int sum;
          int sub;
          int gcd;
      } segTree[MAXN * 4];
      int arr[MAXN];
      void build(int i, int l, int r) {
          segTree[i].l = l;
          segTree[i].r = r;
          if (l == r) return;
          int mid = l + r >> 1;
          build(i << 1, l, mid);
          build(i << 1 | 1, mid + 1, r);
      }
      void update(int i, int index, int val) {
          if (segTree[i].l == segTree[i].r) {
              segTree[i].sum = val;
              segTree[i].sub = max(val, -val);
              segTree[i].gcd = segTree[i].sub;
              return;
          }
          int mid = segTree[i].l + segTree[i].r >> 1;
          if (index <= mid) update(i << 1, index, val);
          else update(i << 1 | 1, index, val);
          segTree[i].sum = segTree[i << 1].sum + segTree[i << 1 | 1].sum;
          segTree[i].sub = max(segTree[i << 1].sub, segTree[i << 1 | 1].sub);
          segTree[i].gcd = __gcd(segTree[i << 1].gcd, segTree[i << 1 | 1].gcd);
      }
      int query(int i, int op, int l, int r) {
          if (l <= segTree[i].l && r >= segTree[i].r) {
              if (op == 1) return segTree[i].sum;
              if (op == 2) return segTree[i].sub;
              if (op == 3) return segTree[i].gcd;
          }
          int mid = segTree[i].l + segTree[i].r >> 1;
          int ans = 0;
          if (op == 1) {
              if (l <= mid) ans += query(i << 1, 1, l, r);
              if (r > mid) ans += query(i << 1 | 1, 1, l, r);
          } else if (op == 2) {
              if (l <= mid) ans = max(ans, query(i << 1, 2, l, r));
              if (r > mid) ans = max(ans, query(i << 1 | 1, 2, l, r));
          } else {
              if (l <= mid) ans = __gcd(ans, query(i << 1, 3, l, r));
              if (r > mid) ans = __gcd(ans, query(i << 1 | 1, 3, l, r));
          }
          return ans;
      }
      int main() {
          int n, m; 
          scanf("%d%d", &n, &m); build(1, 1, n);
          for (int i = 1; i <= n; i++) scanf("%d", &arr[i]);
          for (int i = n; i >= 1; i--) {
              arr[i] -= arr[i - 1];
              update(1, i, arr[i]);
          }
          while (m--) {
              int op, l, r, x;
              scanf("%d", &op);
              if (op == 1) {
                  scanf("%d%d%d", &l, &r, &x);
                  arr[l] += x;
                  update(1, l, arr[l]);
                  if (r + 1 <= n) {
                      arr[r + 1] -= x;
                      update(1, r + 1, arr[r + 1]);
                  }
              } else if (op == 2) {
                  scanf("%d%d", &l, &r);
                  if (l == r) puts("0");
                  else printf("%d
      ", query(1, 2, l + 1, r));
              } else {
                  scanf("%d%d", &l, &r);
                  if (l == r) printf("%d
      ", query(1, 1, 1, l));
                  else printf("%d
      ", __gcd(query(1, 1, 1, l), query(1, 3, l + 1, r)));
              }
          }
          return 0;
      }
  • 相关阅读:
    1253:抓住那头牛
    1251:仙岛求药
    1330:【例8.3】最少步数
    1329:【例8.2】细胞
    1216:红与黑
    1217:棋盘问题
    回溯法与深度优先搜索的关系
    自然数的拆分
    100——第35例
    100——第34例
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/11182060.html
Copyright © 2011-2022 走看看