思考这道题时总是不解为什么用四个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
*/