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
分析:开方最多log(MAXN)次,最终区间会变成一段段连续的数字,然后就可以区间开方了。
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#define INF 0x3f3f3f3f
#define eps 1e-9
#define MAXN 400005
using namespace std;
struct Segtree
{
int l,r;
long long val,tot,down;
bool yy;
}tree[MAXN];
void push_down(int i)
{
if(!tree[i].down) return;
tree[2*i].down += tree[i].down;
tree[2*i+1].down += tree[i].down;
tree[2*i].tot += (tree[2*i].r-tree[2*i].l+1ll)*tree[i].down;
tree[2*i+1].tot += (tree[2*i+1].r-tree[2*i+1].l+1ll)*tree[i].down;
if(tree[2*i].yy) tree[2*i].val += tree[i].down;
if(tree[2*i+1].yy) tree[2*i+1].val += tree[i].down;
tree[i].down = 0;
}
void build(int i,int l,int r)
{
tree[i].l = l;
tree[i].r = r;
tree[i].down = 0;
if(l == r)
{
scanf("%I64d",&tree[i].val);
tree[i].tot = tree[i].val;
tree[i].yy = true;
return;
}
int mid = (l+r) >> 1;
build(2*i,l,mid);
build(2*i+1,mid+1,r);
if(tree[2*i].yy && tree[2*i+1].yy && tree[2*i].val == tree[2*i+1].val)
{
tree[i].yy = true;
tree[i].val = tree[2*i].val;
}
else tree[i].yy = false;
tree[i].tot = tree[2*i].tot + tree[2*i+1].tot;
}
int T,n,m;
void add(int i,int x,int y,int val)
{
int l = tree[i].l,r = tree[i].r;
if(l == x && r == y)
{
tree[i].tot += (y-x+1ll)*val;
if(tree[i].yy) tree[i].val += val;
tree[i].down += val;
return;
}
push_down(i);
int mid = (l+r)/2;
if(y <= mid) add(2*i,x,y,val);
else
if(x <= mid)
{
add(2*i,x,mid,val);
add(2*i+1,mid+1,y,val);
}
else add(2*i+1,x,y,val);
if(tree[2*i].yy && tree[2*i+1].yy && tree[2*i].val == tree[2*i+1].val)
{
tree[i].yy = true;
tree[i].val = tree[2*i].val;
}
else tree[i].yy = false;
tree[i].tot = tree[2*i].tot + tree[2*i+1].tot;
}
void sqrtt(int i,int x,int y)
{
int l = tree[i].l,r = tree[i].r;
if(l == x && r == y && tree[i].yy)
{
tree[i].down += int(sqrt(tree[i].val))-tree[i].val;
tree[i].val = int(sqrt(tree[i].val));
tree[i].tot = tree[i].val*(y-x+1ll);
return;
}
push_down(i);
int mid = (l+r)/2;
if(y <= mid) sqrtt(2*i,x,y);
else
if(x <= mid)
{
sqrtt(2*i,x,mid);
sqrtt(2*i+1,mid+1,y);
}
else sqrtt(2*i+1,x,y);
if(tree[2*i].yy && tree[2*i+1].yy && tree[2*i].val == tree[2*i+1].val)
{
tree[i].yy = true;
tree[i].val = tree[2*i].val;
}
else tree[i].yy = false;
tree[i].tot = tree[2*i].tot + tree[2*i+1].tot;
}
long long sumup(int i,int x,int y)
{
int l = tree[i].l,r = tree[i].r;
if(l == x && r == y) return tree[i].tot;
push_down(i);
int mid = (l+r)/2;
if(y <= mid) return sumup(2*i,x,y);
else
if(x <= mid) return sumup(2*i,x,mid) + sumup(2*i+1,mid+1,y);
else return sumup(2*i+1,x,y);
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i = 1;i <= m;i++)
{
int c;
scanf("%d",&c);
if(c == 1)
{
int x,y,val;
scanf("%d%d%d",&x,&y,&val);
add(1,x,y,val);
}
else
if(c == 2)
{
int x,y;
scanf("%d%d",&x,&y);
sqrtt(1,x,y);
}
else
{
int x,y;
scanf("%d%d",&x,&y);
printf("%I64d\n",sumup(1,x,y));
}
}
}
}