题目传送门
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
struct node {
long long val, minn; //val生命值 minn生命非负最小值(若所有值都<0 则minn=-1)
int cnt, die, sed; //cnt生命非负最小值数量 die死亡人数 sed(shield护盾)护盾数量
friend node operator + (node a, node b) {
node c;
if (a.minn == b.minn) {
if (a.minn >= 0) {
c.minn = a.minn;
c.cnt = a.cnt + b.cnt;
} else
c.minn = -1, c.cnt = 0;
} else {
if (a.minn > b.minn)
swap(a, b);
if (a.minn >= 0)
c.minn = a.minn, c.cnt = a.cnt;
else if (b.minn >= 0)
c.minn = b.minn, c.cnt = b.cnt;
else
c.minn = -1, c.cnt = 0;
}
c.die = a.die + b.die;
c.sed = a.sed + b.sed;
return c;
}
} tree[N << 2];
long long tag[N << 2], a[N];
void pushup(int rt) {
tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
}
void build(int l, int r, int rt) {
if (l == r) {
tree[rt].val = tree[rt].minn = a[l];
tree[rt].cnt = 1, tree[rt].sed = tree[rt].die = 0;
return ;
}
int mid = l + r >> 1;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
pushup(rt);
}
void pushdown(int l, int r, int rt) {
if (tag[rt]) {
tag[rt << 1] += tag[rt], tag[rt << 1 | 1] += tag[rt];
tree[rt << 1].minn += tag[rt], tree[rt << 1 | 1].minn += tag[rt];
tag[rt] = 0;
}
}
void update1(int l, int r, int rt, int L, int R, int c) {//攻击
if (tree[rt].die == r - l + 1)
return ;
int mid = l + r >> 1;
if (L <= l && r <= R) {
if (!tree[rt].sed) {
if (tree[rt].minn >= -c) {
tree[rt].minn += c;
tag[rt] += c;
} else {
if (l == r) {
tree[rt].val += c, tree[rt].minn = -1;
tree[rt].cnt = tree[rt].sed = 0, tree[rt].die = 1;
} else {
pushdown(l, r, rt);
if (L <= mid)
update1(l, mid, rt << 1, L, R, c);
if (R > mid)
update1(mid + 1, r, rt << 1 | 1, L, R, c);
pushup(rt);
}
}
} else {
if (l == r)
tree[rt].sed--;
else {
pushdown(l, r, rt);
if (L <= mid)
update1(l, mid, rt << 1, L, R, c);
if (R > mid)
update1(mid + 1, r, rt << 1 | 1, L, R, c);
pushup(rt);
}
}
return ;
}
pushdown(l, r, rt);
if (L <= mid)
update1(l, mid, rt << 1, L, R, c);
if (R > mid)
update1(mid + 1, r, rt << 1 | 1, L, R, c);
pushup(rt);
}
void update2(int l, int r, int rt, int L, int R, int c) {//治疗
if (tree[rt].die == r - l + 1)
return ;
int mid = l + r >> 1;
if (L <= l && r <= R) {
if (!tree[rt].die) {
tree[rt].minn += c;
tag[rt] += c;
} else {
pushdown(l, r, rt);
if (L <= mid)
update2(l, mid, rt << 1, L, R, c);
if (R > mid)
update2(mid + 1, r, rt << 1 | 1, L, R, c);
pushup(rt);
}
return ;
}
pushdown(l, r, rt);
if (L <= mid)
update2(l, mid, rt << 1, L, R, c);
if (R > mid)
update2(mid + 1, r, rt << 1 | 1, L, R, c);
pushup(rt);
}
void update3(int l, int r, int rt, int p, int c) {//护盾
if (l == r) {
if (!tree[rt].die)
tree[rt].sed++;
return ;
}
pushdown(l, r, rt);
int mid = l + r >> 1;
if (p <= mid)
update3(l, mid, rt << 1, p, c);
if (p > mid)
update3(mid + 1, r, rt << 1 | 1, p, c);
pushup(rt);
}
node query(int l, int r, int rt, int L, int R) {
if (L <= l && r <= R)
return tree[rt];
pushdown(l, r, rt);
node ans;
ans.minn = ans.val = -1;
ans.cnt = ans.die = ans.sed = 0;
int mid = l + r >> 1;
if (L <= mid)
ans = ans + query(l, mid, rt << 1, L, R);
if (R > mid)
ans = ans + query(mid + 1, r, rt << 1 | 1, L, R);
return ans;
}
int main() {
freopen("simulator.in", "r", stdin);
freopen("simulator.out", "w", stdout);
int n, q;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
scanf("%d", &q);
build(1, n, 1);
while (q--) {
int pos, l, r;
long long x;
scanf("%d %d", &pos, &l);
if (pos == 1) {
scanf("%d %lld", &r, &x);
update1(1, n, 1, l, r, -x);
} else if (pos == 2) {
scanf("%d %lld", &r, &x);
update2(1, n, 1, l, r, x);
} else if (pos == 3)
update3(1, n, 1, l, 1);
else if (pos == 4) {
scanf("%d", &r);
int ans = query(1, n, 1, l, r).die;
printf("%d\n", ans);
} else {
scanf("%d", &r);
node tmp = query(1, n, 1, l, r);
int ans = 0;
if (tmp.minn == 0)
ans = tmp.cnt;
printf("%d\n", ans);
}
}
return 0;
}