Description
berber走进机房,边敲门边喊:“我是哔哔”
CRAZY转过头:“我警告你,哔哔刚刚来过!”
“呵呵呵呵……”
这时,哔哔站了起来,环顾四周:“你们笑什么?……”
巧了,发出笑声的人都排成了一排,每个人刚开始发出的笑声值为a[i]的笑声。但是有些笑声哔哔是听不出来的,他只听得出笑声值只包含2和3的数字,比如说什么2333。
但是同学们还是很会秀操作的。对于操作add l r x表示l到r的同学的笑声值同时加上x。数据保证操作完的x在2*10^4以内。
但是,哔哔还是很想知道哪些人在笑。对于count l r表示询问l到r的同学中有多少个笑声值是哔哔听得出来的(就是只由2和3组成)。
哔哔是很忙的,他需要坐在旁边的你来帮他完成这个问题。
Solution
首先x是正数,在20000内只有30个数用贡献,我们用线段树维护每个数离最近有贡献数多少,维护区间最小,最小有多少个,及一个最小的位置。只要最小值小于0就暴力重构那个点,移到离下一个数的距离。
code
using namespace std;
int const mn=3*1e5+9,inf=1e9+7;
int n,m,a[mn],b[mn],pos[mn*4],cnt[mn*4],mi[mn*4],tag[mn*4];
void uptag(int p){
mi[p*2]-=tag[p];
mi[p*2+1]-=tag[p];
tag[p*2]+=tag[p];
tag[p*2+1]+=tag[p];
tag[p]=0;
}
void updata(int p){
if(mi[p*2]==mi[p*2+1]){
pos[p]=pos[p*2];
cnt[p]=cnt[p*2]+cnt[p*2+1];
mi[p]=mi[p*2];
}else{
int tmp=(mi[p*2]*2+1])?p*2:p*2+1;
pos[p]=pos[tmp];
cnt[p]=cnt[tmp];
mi[p]=mi[tmp];
}
}
void oper(int p,int l,int r,int u,int v){
if((l!=r)&&tag[p])uptag(p);
int mid=(l+r)/2;
if(l==r){
pos[p]=l;
cnt[p]=1;
mi[p]=v;
return;
}
if(u<=mid)oper(p*2,l,mid,u,v);
else oper(p*2+1,mid+1,r,u,v);
updata(p);
}
void ope2(int p,int l,int r,int u,int v,int w){
if((l!=r)&&tag[p])uptag(p);
int mid=(l+r)/2;
if((l==u)&&(r==v)){
mi[p]-=w;
tag[p]+=w;
return;
}
if(v<=mid)ope2(p*2,l,mid,u,v,w);
else if(mid*2+1,mid+1,r,u,v,w);
else ope2(p*2,l,mid,u,mid,w),ope2(p*2+1,mid+1,r,mid+1,v,w);
updata(p);
}
int qury(int p,int l,int r,int u,int v){
if((l!=r)&&tag[p])uptag(p);
int mid=(l+r)/2;
if((l==u)&&(r==v)){
return (mi[p]==0)?cnt[p]:0;
}
if(v<=mid)return qury(p*2,l,mid,u,v);
else if(midreturn qury(p*2+1,mid+1,r,u,v);
else return qury(p*2,l,mid,u,mid)+qury(p*2+1,mid+1,r,mid+1,v);
}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d%d",&n,&m);
fo(i,1,20000){
int ii=i,ok=1;
while(ii){
if((ii%10!=2)&&(ii%10!=3)){
ok=0;
break;
}
ii/=10;
}
if(ok)b[++b[0]]=i;
}
fo(i,1,n){
scanf("%d",&a[i]);
int tmp;
fo(j,1,b[0])if(b[j]>=a[i]){
oper(1,1,n,i,b[j]-a[i]);
tmp=j;
break;
}
if(a[i]>b[b[0]])oper(1,1,n,i,inf),tmp=b[0]+1;
a[i]=tmp;
}
fo(cas,1,m){
char ch=getchar();
while((ch!='c')&&(ch!='a'))ch=getchar();
if(ch=='c'){
int l,r;
scanf("ount%d%d",&l,&r);
printf("%d\n",qury(1,1,n,l,r));
}else{
int l,r,x,tmp;
scanf("dd%d%d%d",&l,&r,&x);
ope2(1,1,n,l,r,x);
while(mi[1]<0){
oper(1,1,n,tmp=pos[1],(a[pos[1]]0])?b[a[pos[1]]+1]-b[a[pos[1]]]+mi[1]:inf);
a[tmp]++;
}
}
}
return 0;
}