/**
G :Naive Operations
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6315
题意:给出一个长度为n初值为0的a数组,以及长度为n的b数组;
接下来q次操作,add(l,r) 使得数组a区间l~r所有元素+1,或者查询l~r区间a[i]/b[i]的和
思路:维护区间的a的最大值和b的最小值,使用lazy标记就不需要更新到每个点了。
每次更新当当前最大值a小于最小的b,那么下面子节点就都不需要查询了
大于时我们暴力找到l==r然后cnt+1,同时分母+上b[l];
比如当前是2/2 我们就把它变成 2/4 这样我们还需要增加2次才能到达4/4 再变成4/6.
借鉴了别人的思路和代码.......赛中这个题也是想着如何增上去 也没有仔细的想 其实反过来想的话 还是挺好想的吧;
*/
#include<bits/stdc++.h>
using namespace std;
#define Lson l,m,rt<<1
#define Rson m+1,r,rt<<1|1
#define pll pair<int,int>
#define mp make_pair
#define ll long long
#define INF 0x3f3f3f3f
const int maxn=1e5+5;
int n,q;
struct node{
int cnt,addv,minb,maxa;
} tree[maxn<<2];
int b[maxn];
void push_up(int rt){
tree[rt].minb=min(tree[rt<<1].minb,tree[rt<<1|1].minb);
tree[rt].cnt=tree[rt<<1].cnt+tree[rt<<1|1].cnt;
tree[rt].maxa=max(tree[rt<<1].maxa,tree[rt<<1|1].maxa);
}
void push_down(int rt){
if(tree[rt].addv){
int v=tree[rt].addv;
tree[rt].addv=0;
tree[rt<<1].maxa+=v;
tree[rt<<1|1].maxa+=v;
tree[rt<<1].addv+=v;
tree[rt<<1|1].addv+=v;
}
}
void build(int l,int r,int rt){
tree[rt].addv=0;
if(l==r){
tree[rt].cnt=tree[rt].maxa=0;
tree[rt].minb=b[l];
return;
}
int m=l+r>>1;
build(Lson);
build(Rson);
push_up(rt);
}
void updata(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
tree[rt].maxa++;
if(tree[rt].maxa<tree[rt].minb){
tree[rt].addv++;
return;
}
if(l==r&&tree[rt].maxa>=tree[rt].minb){
tree[rt].cnt++;
tree[rt].minb+=b[l];
return;
}
}
push_down(rt);
int m=l+r>>1;
if(L<=m) updata(L,R,Lson);
if(R>m) updata(L,R,Rson);
push_up(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R) return tree[rt].cnt;
int m=l+r>>1;
push_down(rt);
int ans=0;
if(L<=m) ans+=query(L,R,Lson);
if(R>m) ans+=query(L,R,Rson);
return ans;
}
int main(){
int n,x,y;
while(~scanf("%d %d",&n,&q)){
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
build(1,n,1);
char pp[6];
int l,r;
while(q--){
scanf("%s%d%d",pp,&l,&r);
if(pp[0]=='a') updata(l,r,1,n,1);
else printf("%d\n",query(l,r,1,n,1));
}
}
return 0;
}