题意:
给定序列a,b;a初始值为0,b是1-n的排列;
每次对a序列操作:
add L R操作是给a序列 区间【L-R】每个值+1;
query L R操作是对区间【L-R】对应的 [a[i] / b[i]](向下取整) 求和;
思路:
令ans[i] = a[i] / b[i] (向下取整), 首先可以想到,要使ans[i]加一的话,a[i]需要加 b[i] ,这样每时每刻都会存在一个最小的t[i] ,使得a[i]+t[i] 能令ans[i] +1,也就是我代码中维护的min_[] 值,会随着对a[]数组更新而减小
我们要维护的就是这个min_[]值,还要进行一下线段树的lazy操作(即我代码中的add[]数组),如果min[i]为负数,意味着这个区间有个子区间可以满足使ans[i] +1;继续往下更新或查询;
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 100010;
typedef long long ll;
int n, q;
int b[maxn];
int min_[maxn<<2];
ll sum[maxn<<2];
int add[maxn<<2];
void push_up(int id) {
min_[id] = min(min_[id<<1], min_[(id<<1|1)]);
sum[id] = sum[id<<1] + sum[(id<<1)|1];
}
void build(int id, int l_, int r_) {
sum[id] = 0;
add[id] = 0;
if(l_ == r_) {
min_[id] = b[l_];
return;
}
int mid = (l_ + r_) >> 1;
build(id<<1, l_, mid);
build((id<<1)|1, mid+1, r_);
push_up(id);
}
void push_down(int id, int num) {
add[id<<1] += num;
add[(id<<1)|1] += num;
min_[id<<1] -= num;
min_[(id<<1)|1] -= num;
add[id] = 0;
}
void update(int id, int l_, int r_, int ul, int ur) {
if(ul > r_ || ur < l_)
return;
if(ul == l_ && ur == r_) {
add[id] += 1;
min_[id] -= 1;
return;
}
push_down(id, add[id]);
int mid = (l_ + r_) / 2;
if(ul > mid) {
update((id<<1)|1, mid+1, r_, ul, ur);
} else if(ur <= mid) {
update((id<<1), l_, mid, ul, ur);
} else {
update((id<<1), l_, mid, ul, mid);
update((id<<1)|1, mid+1, r_, mid+1, ur);
}
push_up(id);
}
void query(int id, int l_, int r_) {
if(l_ == r_) {
if(min_[id] > 0)
return;
int t = add[id] / b[l_];
add[id] %= b[l_];
sum[id] += t;
min_[id] = b[l_] - add[id];
return;
}
if(min_[id] > 0) return;
push_down(id, add[id]);
int mid = (l_ + r_) / 2;
query(id<<1, l_, mid);
query((id<<1)|1, mid+1, r_);
push_up(id);
}
ll query1(int id, int l_, int r_, int ql, int qr) {
if(ql > r_ || qr < l_)
return 0;
if(ql == l_ && qr == r_) {
return sum[id];
}
//int res = 0;
int mid = (l_ + r_) >> 1;
if(ql > mid) {
return query1((id<<1)|1, mid+1, r_, ql, qr);
} else if(qr <= mid) {
return query1(id<<1, l_, mid, ql, qr);
} else {
return query1(id<<1, l_, mid, ql, mid) + query1((id<<1)|1, mid+1, r_, mid+1, qr);
}
}
int main() {
while(~scanf("%d%d", &n, &q)) {
for(int i = 1; i <= n; ++i) {
scanf("%d", &b[i]);
}
build(1, 1, n);
char s[17];
int L, R;
int f = 0;
for(int i = 0; i < q; ++i) {
scanf("%s", s);
if(s[0] == 'a') {
scanf("%d%d", &L, &R);
update(1,1,n,L,R);
f = 1;
} else if(s[0] == 'q') {
scanf("%d%d", &L, &R);
if(f)
query(1, 1, n);
f = 0;
ll anss = query1(1, 1, n, L, R);
printf("%lld\n", anss);
}
}
}
return 0;
}