#include<iostream>
using namespace std;
int n,m,q;
const int N=5e5+10;
struct tree{
int l,r;
int up,down;
long long num;
}tr[N<<2];
void push_up(tree &a,const tree b,const tree c){
if((!b.up&&!b.down)){
a=c;
}else if(!c.up&&!c.down){
a=b;
}else{
if(b.down>c.up){
a.up=b.up;
a.down=b.down-c.up+c.down;
a.num=((b.num>>c.up)<<c.down)+c.num;
}else{
a.up=b.up+c.up-b.down;
a.down=c.down;
a.num=c.num;
}
}
}
void build(int u,int l,int r){
tr[u].l=l,tr[u].r=r;
if(l==r){
int v;
scanf("%d",&v);
tr[u].up=tr[u].down=tr[u].num=0;
if(v==1){
tr[u].down=1;
}else if(v==2){
tr[u].down=tr[u].num=1;
}else{
tr[u].up=1;
}
return;
}
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
push_up(tr[u],tr[u<<1],tr[u<<1|1]);
}
void modify(int u,int x,int v){
if(tr[u].l==tr[u].r){
tr[u].up=tr[u].down=tr[u].num=0;
if(v==1){
tr[u].down=1;
}else if(v==2){
tr[u].down=tr[u].num=1;
}else{
tr[u].up=1;
}
return;
}
int mid=(tr[u].l+tr[u].r)>>1;
if(x<=mid){
modify(u<<1,x,v);
}else{
modify(u<<1|1,x,v);
}
push_up(tr[u],tr[u<<1],tr[u<<1|1]);
}
tree query(int u,int l,int r){
if(tr[u].l>=l&&tr[u].r<=r){
return tr[u];
}
int mid=(tr[u].l+tr[u].r)>>1;
if(r<=mid){
return query(u<<1,l,r);
}
if(l>mid){
return query(u<<1|1,l,r);
}
tree a;
tree b=query(u<<1,l,r);
tree c=query(u<<1|1,l,r);
push_up(a,b,c);
return a;
}
int main(){
cin>>n>>m>>q;
build(1,1,m);
while(q--){
int type;
scanf("%d",&type);
if(type==1){
long long st;
int l,r;
scanf("%lld%d%d",&st,&l,&r);
tree ans=query(1,l,r);
printf("%lld\n",1ll*(max(1ll,st>>ans.up)<<ans.down)+1ll*ans.num);
}else{
int x,y;
scanf("%d%d",&x,&y);
modify(1,x,y);
}
}
}
搞不懂。