Rikka with Sequence
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:
Yuta has an array A with n numbers. Then he makes m operations on it.
There are three type of operations:
1 l r x : For each i in [l,r], change A[i] to A[i]+x
2 l r : For each i in [l,r], change A[i] to ⌊A‾‾√[i]⌋
3 l r : Yuta wants Rikka to sum up A[i] for all i in [l,r]
It is too difficult for Rikka. Can you help her?
区间开根号,区间+,区间查询和
const long long maxn = 1e6+11;
long long sum[maxn],minv[maxn],maxv[maxn],lazy[maxn],tag[maxn];//lazy,tag均为懒惰标记
void pushup(long long i)
{
sum[i] = sum[i<<1] + sum[i<<1|1];
maxv[i] = max(maxv[i<<1],maxv[i<<1|1]);
minv[i] = min(minv[i<<1],minv[i<<1|1]);
}
void pushcover(long long i,long long l,long long r,long long v)
{
lazy[i] = 0;
sum[i] = (r-l+1)*v;
tag[i] = maxv[i] = minv[i] = v;
}
void pushnow(long long i,long long l,long long r,long long v)
{
sum[i] += (r-l+1)*v;
lazy[i] += v;
maxv[i] += v;
minv[i] += v;
}
void pushdown(long long i,long long l,long long r)
{
long long mid = (l+r)>>1;
if(tag[i]!=-1)
{
pushcover(i<<1,l,mid,tag[i]);
pushcover(i<<1|1,mid+1,r,tag[i]);
tag[i] = -1;
}
if(lazy[i])
{
pushnow(i<<1,l,mid,lazy[i]);
pushnow(i<<1|1,mid+1,r,lazy[i]);
lazy[i] = 0;
}
}
void update1(long long i,long long l,long long r,long long ql,long long qr,long long v)
{
//if(ql > r || qr < l)return;
if(ql <= l && r <= qr)
{
pushnow(i,l,r,v);return;
}
long long mid = (l+r)>>1;
pushdown(i,l,r);
if(ql <= mid)update1(i<<1,l,mid,ql,qr,v);
if(qr > mid)update1(i<<1|1,mid+1,r,ql,qr,v);
pushup(i);
}
void update2(long long i,long long l,long long r,long long ql,long long qr)
{
//if(ql > r || qr < l)return;
if(ql <= l && qr >= r && maxv[i] - minv[i] <= 1)
{
long long x = sqrt(maxv[i]),y = sqrt(minv[i]);
if(x == y)pushcover(i,l,r,x);//区间一样
else pushnow(i,l,r,x-maxv[i]);//区间-
return;
}
long long mid = (l+r)>>1;
pushdown(i,l,r);
if(ql <= mid)update2(i<<1,l,mid,ql,qr);
if(qr > mid)update2(i<<1|1,mid+1,r,ql,qr);
pushup(i);
}
long long query(long long i,long long l,long long r,long long ql,long long qr)
{
if(ql<=l && qr>=r)return sum[i];
long long mid = (l+r)>>1;
pushdown(i,l,r);
long long ans = 0;
if(ql<=mid) ans += query(i<<1,l,mid,ql,qr);
if(qr>mid) ans+=query(i<<1|1,mid+1,r,ql,qr);
return ans;
}
void build(long long i,long long l,long long r)
{
lazy[i] = 0,tag[i] = -1;
long long mid = (l+r)>>1;
if(l==r)
{
long long x;
scanf("%lld",&x);
maxv[i] = minv[i] = sum[i] = x;
return;
}
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
pushup(i);
}
int main()
{
long long T;cin>>T;
while(T--)
{
long long n,m;scanf("%lld%lld",&n,&m);
build(1,1,n);
while(m--)
{
long long op,l,r;
scanf("%lld%lld%lld",&op,&l,&r);
if(op == 1)
{long long v;scanf("%lld",&v),update1(1,1,n,l,r,v);}//区间+
else if(op == 2)
update2(1,1,n,l,r);//区间开根号
else printf("%lld\n",query(1,1,n,l,r)); //区间
}
}
return 0;
}