使用 线段树 维护 , 初值为 , 每次修改时, 若一个位置上的值变为了 , 则说明其会对答案产生新的贡献,
在外部使用 树状数组 将贡献计入答案, 然后将该位置的值 重置为 , 重置的时间复杂度是 .
考虑最坏情况, 每次操作 ,
这样 的位置最多重置 次 最多重置 次, 最多 …
所以总共需要 重置 次, 总时间复杂度 .
重置 可以在 修改 时 使用 实现 .
#include<bits/stdc++.h>
#define reg register
#define fi first
#define se second
typedef std::pair<int, int> pr;
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 100005;
const int inf = 0x3f3f3f3f;
int N;
int M;
int Tmp_1;
int B[maxn];
struct Bit_Tree{
int v[maxn], lim;
void Add(int k, int x){ while(k<=lim)v[k]+=x,k+=k&-k; }
int Query(int k){ if(k<=0)return 0; int s=0; while(k)s+=v[k],k-=k&-k; return s; }
} bit_t;
struct Segment_Tree{
struct Node{ int l, r, t, max_v, id; } T[maxn << 2];
void Push_down(const int &k){
T[k].max_v += T[k].t;
if(T[k].l == T[k].r) return T[k].t = 0, void();
T[k<<1].t += T[k].t, T[k<<1|1].t += T[k].t, T[k].t = 0;
}
void Push_up(const int &k){
if(T[k<<1].t) Push_down(k<<1);
if(T[k<<1|1].t) Push_down(k<<1|1);
T[k].max_v = std::max(T[k<<1].max_v, T[k<<1|1].max_v);
if(T[k<<1].max_v == T[k].max_v) T[k].id = k<<1;
else T[k].id = k<<1|1;
}
void Build(int k, int l, int r){
T[k].l = l, T[k].r = r; if(l == r) return T[k].max_v = B[l], T[k].id = k, void();
int mid = l+r >> 1; Build(k<<1, l, mid), Build(k<<1|1, mid+1, r); Push_up(k);
}
void update(int k){
int l = T[k].l, r = T[k].r;
if(T[k].t) Push_down(k);
if(l == r) return bit_t.Add(l, 1), T[k].max_v=B[l], void();
update(T[k].id); Push_up(k);
}
void Modify(int k, const int &ql, const int &qr, const int &aim){
int l = T[k].l, r = T[k].r;
if(T[k].t) Push_down(k);
if(r < ql || l > qr) return ;
if(ql <= l && r <= qr){
T[k].t += aim, Push_down(k);
while(!T[k].max_v) update(k);
return ;
}
Modify(k<<1, ql, qr, aim), Modify(k<<1|1, ql, qr, aim); Push_up(k);
}
int Query(int k, const int &ql, const int &qr){
int l = T[k].l, r = T[k].r;
if(T[k].t) Push_down(k);
if(r < ql || l > qr) return -inf;
if(ql <= l && r <= qr) return T[k].max_v;
return std::max(Query(k<<1, ql, qr), Query(k<<1|1, ql, qr));
}
} seg_t;
int main(){
N = read(), M = read();
for(reg int i = 1; i <= N; i ++) B[i] = -read();
seg_t.Build(1, 1, N); bit_t.lim = N;
for(reg int i = 1; i <= M; i ++){
int opt = read(), l = read(), r = read();
if(opt == 2) printf("%d
", bit_t.Query(r) - bit_t.Query(l-1));
else seg_t.Modify(1, l, r, 1);
}
return 0;
}