题意:给你一段固定的序列1~n,当作分母,两次操作:add,L,R,区间所有的分子+1;query,L,R,查询区间和
a[i]/b[i](向下取整)
a
[
i
]
/
b
[
i
]
(
向
下
取
整
)
.
分析:
区间维护sum和lazy,暴力更新lazy会TLE。由于分母固定,那就维护一个区间
sub[root]=min(b[i]−a[i]
s
u
b
[
r
o
o
t
]
=
m
i
n
(
b
[
i
]
−
a
[
i
]
%
b[i])
b
[
i
]
)
,只有当
sub[root]=0
s
u
b
[
r
o
o
t
]
=
0
时,才会更新lazy和sum。
ps:注意一点,实时更新sub值,不然lazy值的覆盖会导致sum出错.
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 4e5 + 10;
int b[MAXN];
int sub[MAXN], sum[MAXN], lazy[MAXN];
void up(int root) {
sum[root] = sum[root << 1] + sum[root << 1 | 1];
sub[root] = min(sub[root << 1], sub[root << 1 | 1]);
}
void down(int root) {
lazy[root << 1] += lazy[root], sub[root << 1] -= lazy[root];
lazy[root << 1 | 1] += lazy[root], sub[root << 1 | 1] -= lazy[root];
lazy[root] = 0;
}
void build(int root, int L, int R) {
sum[root] = 0;
lazy[root] = 0; //切记在区间前更新
if(L == R) {
scanf("%d", &b[L]);
sub[root] = b[L];
return ;
}
int mid = (L + R) >> 1;
build(root << 1, L, mid);
build(root << 1 | 1, mid + 1, R);
up(root);
}
void update1(int root, int L, int R) {
if(L == R) {
sum[root]++;
sub[root] = b[L];
return ;
}
int mid = (L + R) >> 1;
down(root);
if(!sub[root << 1]) update1(root << 1, L, mid);
if(!sub[root << 1 | 1]) update1(root << 1 | 1, mid + 1, R);
up(root);
}
void update(int root, int L, int R, int l, int r) {
if(L >= l && R <= r) {
lazy[root]++;
sub[root]--;
if(!sub[root]) update1(root, L, R);
return ;
}
int mid = (L + R) >> 1;
down(root);
if(l <= mid) update(root << 1, L, mid, l, r);
if(r > mid) update(root << 1 | 1, mid + 1, R, l, r);
up(root);
}
int query(int root, int L, int R, int l, int r) {
if(L >= l && R <= r) {
return sum[root];
}
int ans = 0;
int mid = (L + R) >> 1;
down(root);
if(l <= mid) ans += query(root << 1, L, mid, l, r);
if(r > mid) ans += query(root << 1 | 1, mid + 1, R, l, r);
up(root);
return ans;
}
int main() {
int n, q;
while(scanf("%d %d", &n, &q) != EOF) {
build(1, 1, n);
char s[10];
int a, b;
while(q--) {
scanf("%s%d%d", s, &a, &b);
if(s[0] == 'a') update(1, 1, n, a, b);
else printf("%d\n", query(1, 1, n, a, b));
}
}
return 0;
}