题目链接:HDU 6315
题解: 树状数组 + 线段树。
每一次我们对an加一就相当于对bn-1, 当bn = 0, 代表c[n]++。
树状数组用来单点更新, 区间求和, 线段树用来维护bn当前的值,以及记录最小值。
#include
using namespace std;
const int maxn = 1e5+10;
int n, m, ans, sign;
int c[maxn], b[maxn]; // c 和 b数组就是题目中的意思
int a[maxn<<2], p[maxn<<2], lazy[maxn<<2]; // p数组用来记录最小值的位置 a数组用来记录最小值, lazy标记
int lowbit(int x)
{
return x & (-x);
}
void add(int x)
{
while(x <= n) {
c[x]++;
x += lowbit(x);
}
}
int sum(int x)
{
int tmp = 0;
for(; x > 0; x -= lowbit(x)) tmp += c[x];
return tmp;
}
void up(int rt)
{
if(a[rt<<1] <= a[rt<<1|1]) a[rt] = a[rt<<1], p[rt] = p[rt<<1];
else a[rt] = a[rt<<1|1], p[rt] = p[rt<<1|1];
}
void build(int rt, int l, int r)
{
lazy[rt] = 0;
if(l == r) {
a[rt] = b[l];
p[rt] = l;
return ;
}
int m = (l + r) >> 1;
build(rt<<1, l, m);
build(rt<<1|1, m+1, r);
up(rt);
}
void down(int rt)
{
if(lazy[rt]) {
a[rt<<1] -= lazy[rt];
a[rt<<1|1] -= lazy[rt];
lazy[rt<<1] += lazy[rt];
lazy[rt<<1|1] += lazy[rt];
lazy[rt] = 0;
}
}
void updata(int rt, int L, int R, int l, int r)
{
if(R < l || r < L) return ;
if(L <= l && r <= R) {
a[rt]--, lazy[rt]++;
return ;
}
down(rt);
int m = (l + r) >> 1;
updata(rt<<1, L, R, l, m);
updata(rt<<1|1, L, R, m+1, r);
up(rt);
}
void query(int rt, int L, int R, int l, int r)
{
if(R < l || r < L) return ;
if(L <= l && r <= R) {
if(ans > a[rt]) ans = a[rt], sign = p[rt];
return ;
}
down(rt);
int m = (l + r) >> 1;
query(rt<<1, L, R, l, m);
query(rt<<1|1, L, R, m+1, r);
up(rt);
}
void reset(int rt, int l, int r, int goal)
{
if(l == r && l == goal) {
a[rt] = b[goal];
return ;
}
down(rt);
int m = (l + r) >> 1;
if(goal <= m) reset(rt<<1, l, m, goal);
else reset(rt<<1|1, m+1, r, goal);
up(rt);
}
int main()
{
while(scanf("%d%d", &n, &m) == 2) {
for(int i = 1; i <= n; i++) scanf("%d", b + i);
memset(c, 0, sizeof c);
build(1, 1, n);
for(int i = 0; i < m; i++)
{
int x, y; char op[10];
scanf("%s%d%d", op, &x, &y);
if(op[0] == 'a') {
updata(1, x, y, 1, n);
ans = maxn, sign = -1;
query(1, x, y, 1, n);
while(ans == 0) {
add(sign);
reset(1, 1, n, sign);
ans = maxn, sign = -1;
query(1, x, y, 1, n);
}
}
else printf("%d\n", sum(y) - sum(x-1));
}
}
return 0;
}