Problem Description
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?
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?
Input
The first line contains a number t(1<=t<=100), the number of the testcases. And there are no more than 5 testcases with n>1000.
For each testcase, the first line contains two numbers n,m(1<=n,m<=100000). The second line contains n numbers A[1]~A[n]. Then m lines follow, each line describe an operation.
It is guaranteed that 1<=A[i],x<=100000.
For each testcase, the first line contains two numbers n,m(1<=n,m<=100000). The second line contains n numbers A[1]~A[n]. Then m lines follow, each line describe an operation.
It is guaranteed that 1<=A[i],x<=100000.
Output
For each operation of type 3, print a lines contains one number -- the answer of the query.
Sample Input
1 5 5 1 2 3 4 5 1 3 5 2 2 1 4 3 2 4 2 3 5 3 1 5
Sample Output
5 6
考试的时候写了个近似暴力的东西。。
线段树维护一个Tag表示区间是否相同,相同就直接做sqrt否则往下查找。那时候过了
后来hdu加数据把这个做法卡掉了
其实这个时候只要维护一下区间最小值和最小值+1的个数就可以
3 4,开根再+2这样如果不维护的话就会无限循环
而如果存在最小值和最小值+2,多次开根操作后他们的差会变成1,因而维护min和min+1即可保证复杂度
附考试时候代码。加了补丁的版本没有调出来...
***一开始公布的STD也似乎T掉了***
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree
{
int l,r;
long long s;
long long tag1,tag2;
}tr[800001];
long long a[100001];
inline void up(int p)
{
tr[p].s=tr[p*2].s+tr[p*2+1].s;
if(tr[p*2].tag2==tr[p*2+1].tag2)
tr[p].tag2=tr[p*2].tag2;
else
tr[p].tag2=0;
}
inline void push(int p)
{
if(tr[p].tag2!=0)
{
long long l=tr[p].r-tr[p].l+1;
tr[p*2].s=tr[p].tag2*(l-l/2);
tr[p*2+1].s=tr[p].tag2*(l/2);
tr[p*2].tag1=0;
tr[p*2+1].tag1=0;
tr[p*2].tag2=tr[p].tag2;
tr[p*2+1].tag2=tr[p].tag2;
tr[p].tag1=0;
return ;
}
long long l=tr[p].r-tr[p].l+1;
tr[p*2].s+=tr[p].tag1*(l-l/2);
tr[p*2+1].s+=tr[p].tag1*(l/2);
tr[p*2].tag1+=tr[p].tag1;
tr[p*2+1].tag1+=tr[p].tag1;
if(tr[p*2].tag2!=0)
tr[p*2].tag2+=tr[p].tag1;
if(tr[p*2+1].tag2!=0)
tr[p*2+1].tag2+=tr[p].tag1;
tr[p].tag1=0;
}
inline void build(int p,int l,int r)
{
tr[p].l=l;
tr[p].r=r;
if(l!=r)
{
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
up(p);
}
else
{
tr[p].s=a[l];
tr[p].tag2=a[l];
}
}
inline void inc(int p,int l,int r,long long x)
{
if(l<=tr[p].l&&tr[p].r<=r)
{
if(tr[p].tag2!=0)
{
tr[p].tag2+=x;
tr[p].s=(long long)(tr[p].r-tr[p].l+1)*tr[p].tag2;
tr[p].tag1=0;
}
else
{
tr[p].s+=(long long)(tr[p].r-tr[p].l+1)*x;
tr[p].tag1+=x;
}
}
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
inc(p*2,l,r,x);
if(r>mid)
inc(p*2+1,l,r,x);
up(p);
}
}
inline void sq(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r&&tr[p].tag2!=0)
{
tr[p].tag2=sqrt(tr[p].tag2);
tr[p].s=(long long)(tr[p].r-tr[p].l+1)*tr[p].tag2;
tr[p].tag1=0;
push(p);
}
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
sq(p*2,l,r);
if(r>mid)
sq(p*2+1,l,r);
up(p);
}
}
inline long long ask(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r)
return tr[p].s;
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
long long ans=0;
if(l<=mid)
ans+=ask(p*2,l,r);
if(r>mid)
ans+=ask(p*2+1,l,r);
up(p);
return ans;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T>0)
{
T--;
int n,m;
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=n;i++)
scanf("%I64d",&a[i]);
memset(tr,0,sizeof(tr));
build(1,1,n);
int x,l,r;
for(i=1;i<=m;i++)
{
scanf("%d",&x);
if(x==1)
{
scanf("%d%d%d",&l,&r,&x);
inc(1,l,r,x);
}
else if(x==2)
{
scanf("%d%d",&l,&r);
sq(1,l,r);
}
else
{
scanf("%d%d",&l,&r);
printf("%I64d\n",ask(1,l,r));
}
}
}
return 0;
}