关于两个Tag为什么不对的讨论
查看原帖
关于两个Tag为什么不对的讨论
143771
比利♂海灵顿楼主2021/1/30 20:04

思考这道题时总是不解为什么用四个Tag, 自己打了一份两个Tag的, 找不到问题, 但又过不了.

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
#define Wild_Donkey 0
using namespace std;
inline int RD() {
  int intmp(0), insig(1);
  char rdch(getchar());
  while (rdch < '0' || rdch > '9') {
    if (rdch == '-') {
      insig = -1;
    }
    rdch = getchar();
  }
  while (rdch >= '0' && rdch <= '9') {
    intmp = intmp * 10 + rdch - '0';
    rdch = getchar();
  }
  return intmp * insig;
}
int a[200005];
unsigned int M, n, Cnt(0);
long long Lst, A, B, C, D;
struct Node {
  Node *L, *R;
  int Tagpls, Mx, HisMx, SecMx, Cntmax, Tagmax;
  long long Sum;
} N[1000005], *Cntn(N);
void Udt(Node *x, const unsigned int &l, const unsigned int &r,
         const unsigned int &m) {
  if (l == r) {
    return;
  }
  x->Sum = x->L->Sum + x->R->Sum;  //更新总和
  if (x->L->Mx == x->R->Mx) {      //更新最值和最值数量
    x->Cntmax = x->L->Cntmax + x->R->Cntmax;
    x->Mx = x->L->Mx;
    x->SecMx = max(x->L->SecMx, x->R->SecMx);  //更新次大值
  } else {
    if (x->L->Mx > x->R->Mx) {  //最大值是左边的最大值
      x->Mx = x->L->Mx;
      x->Cntmax = x->L->Cntmax;
      x->SecMx = max(x->R->Mx, x->L->SecMx);  //次大值的两种可能
    } else {                                  //同上
      x->Mx = x->R->Mx;
      x->Cntmax = x->R->Cntmax;
      x->SecMx = max(x->L->Mx, x->R->SecMx);
    }
  }
  x->HisMx = max(x->L->HisMx, x->R->HisMx);  //历史最值
  return;
}
void Bld(Node *x, unsigned int l, const unsigned int &r) {
  x->Tagpls = 0;
  if (l == r) {
    x->Cntmax = 1;
    x->SecMx = -0x3f3f3f3f3f3f3f3f;
    x->Sum = a[l];
    x->Mx = a[l];
    x->HisMx = a[l];
    return;
  }
  unsigned int m((l + r) >> 1);
  Bld(x->L = ++Cntn, l, m);
  Bld(x->R = ++Cntn, m + 1, r);
  Udt(x, l, r, m);
  return;
}
void PsDw(Node *x, const unsigned int &l, const unsigned int &r,
          const unsigned int &m) {
  if (l == r) {  //叶
    return;
  }
  if (x->Tagmax) {
    if (x->L->Mx == x->R->Mx) {  //都有最大值
      x->R->Mx += x->Tagmax;
      x->R->Tagmax += x->Tagmax;
      x->R->Sum += x->R->Cntmax * x->Tagmax;
      x->L->Mx += x->Tagmax;
      x->L->Tagmax += x->Tagmax;
      x->L->Sum += x->L->Cntmax * x->Tagmax;
    } else {
      if (x->L->Mx > x->R->Mx) {  //最值在左边
        x->L->Mx += x->Tagmax;
        x->L->Tagmax += x->Tagmax;
        x->L->Sum += x->L->Cntmax * x->Tagmax;
      } else {  //在右边
        x->R->Mx += x->Tagmax;
        x->R->Tagmax += x->Tagmax;
        x->R->Sum += x->R->Cntmax * x->Tagmax;
      }
    }
    x->Tagmax = 0;
  }
  if (x->Tagpls) {                                    //有Tag
    x->L->Tagpls += x->Tagpls;                        //标记操作
    x->L->Mx += x->Tagpls;                            //最值操作
    x->L->HisMx = max(x->L->Mx, x->L->HisMx);         //是否破纪录
    x->L->Sum += (long long)x->Tagpls * (m - l + 1);  //左边总和
    x->R->Tagpls += x->Tagpls;
    x->R->Mx += x->Tagpls;
    x->R->HisMx = max(x->R->Mx, x->R->HisMx);
    x->R->Sum += (long long)x->Tagpls * (r - m);  //右边总和
    x->Tagpls = 0;
  }
  return;
}
void Addnm(Node *x, unsigned int l, const unsigned int &r) {
  if (l >= B && r <= C) {  //全包
    x->Sum += (long long)(r - l + 1) * D;
    // x->Tagmax += D;
    x->Tagpls += D;
    x->Mx += D;
    x->HisMx = max(x->HisMx, x->Mx);  //历史最值
    return;
  }
  unsigned int m((l + r) >> 1);
  PsDw(x, l, r, m);
  if (B <= m) {  //在左
    Addnm(x->L, l, m);
  }
  if (C > m) {  //在右
    Addnm(x->R, m + 1, r);
  }
  Udt(x, l, r, m);
  return;
}
void Tomin(Node *x, unsigned int l, const unsigned int &r) {
  if (l >= B && r <= C) {  //全包
    if (x->Mx <= D) {      //都不受影响
      return;
    }
    if (x->SecMx < D) {  //最大值受影响
      x->Sum -= (long long)x->Cntmax * (x->Mx - D);
      x->Tagmax += D - x->Mx;
      x->Mx = D;
      return;
    }
  }
  unsigned int m((l + r) >> 1);  //递归
  PsDw(x, l, r, m);
  if (m >= B) {
    Tomin(x->L, l, m);
  }
  if (m < C) {
    Tomin(x->R, m + 1, r);
  }
  Udt(x, l, r, m);
  return;
}
void QrSum(Node *x, unsigned int l, const unsigned int &r) {
  if (l >= B && r <= C) {  //全包
    Lst += x->Sum;
    return;
  }
  unsigned int m((l + r) >> 1);
  PsDw(x, l, r, m);
  if (!(l > C || m < B)) {  //左边
    QrSum(x->L, l, m);
  }
  if (!(m + 1 > C || r < B)) {  //右边
    QrSum(x->R, m + 1, r);
  }
  // Udt(x, l, r, m);
  return;
}
void QMaxA(Node *x, unsigned int l, const unsigned int &r) {
  if (l >= B && r <= C) {  //全包
    Lst = max((long long)x->Mx, Lst);
    return;
  }
  unsigned int m((l + r) >> 1);
  PsDw(x, l, r, m);
  if (!(l > C || m < B)) {
    QMaxA(x->L, l, m);
  }
  if (!(m + 1 > C || r < B)) {
    QMaxA(x->R, m + 1, r);
  }
  // Udt(x, l, r, m);
  return;
}
void QMaxB(Node *x, unsigned int l, const unsigned int &r) {
  // x->HisMx = max(x->Mx, x->HisMx);
  if (l >= B && r <= C) {
    Lst = max(Lst, (long long)x->HisMx);
    return;
  }
  unsigned int m((l + r) >> 1);
  PsDw(x, l, r, m);
  if (!(l > C || m < B)) {
    QMaxB(x->L, l, m);
  }
  if (!(m >= C || r < B)) {
    QMaxB(x->R, m + 1, r);
  }
  // Udt(x, l, r, m);
  return;
}
int main() {
  // double Ti(clock()), Mti(0);
  // freopen("P6242_1.in", "r", stdin);
  // freopen("P3834.out", "w", stdout);
  n = RD();
  M = RD();
  for (register unsigned int i(1); i <= n; ++i) {
    a[i] = RD();
  }
  memset(N, 0, sizeof(N));
  Bld(N, 1, n);
  for (register int i(1); i <= M; ++i) {
    A = RD();
    B = RD();
    C = RD();
    switch (A) {
      case 1: {
        D = RD();
        Addnm(N, 1, n);
        break;
      }
      case 2: {
        D = RD();
        Tomin(N, 1, n);
        break;
      }
      case 3: {
        ++Cnt;
        Lst = 0;
        QrSum(N, 1, n);
        printf("%lld\n", Lst);
        break;
      }
      case 4: {
        ++Cnt;
        Lst = -0x3f3f3f3f3f3f3f3f;
        QMaxA(N, 1, n);
        printf("%lld\n", Lst);
        break;
      }
      case 5: {
        ++Cnt;
        Lst = -0x3f3f3f3f3f3f3f3f;
        QMaxB(N, 1, n);
        printf("%lld\n", Lst);
        break;
      }
      default: {
        printf("FYSNB\n");
        break;
      }
    }
    // if (Cnt == 19) {
    //   Cnt = 19;
    // }
  }
  // Ti = clock() - Ti;
  // printf("Time %lf MTime %lf\n", Ti, Mti);
  // system("pause");
  // fclose(stdin);
  // fclose(stdout);
  return 0;
}
/*
5 6
1 2 3 4 5
2 2 4 3
5 1 4
*/
2021/1/30 20:04
加载中...