分析:这个题目超级无敌虚伪,在对整个块开方的时候你会发现你无从下手,须要知道每一个元素,才能知道他们开方后的和,也就是说,难以快速对一个块信息进行更新。
其实你仔细推一推,你会发现,每次开方后向下取整,其实一个数开几次之后你会发现不是0就是1,所以我们只要对整块进行开方后判断一下是不是成为了0或1,在之后的修改中如果已经是0或1可以直接跳过……QWQ
代码:
//By Bibi
/// .-~~~~~~~~~-._ _.-~~~~~~~~~-.
/// __.' ~. .~ `.__
/// .'// \./ \\`.
/// .'// | \\`.
/// .'// .-~"""""""~~~~-._ | _,-~~~~"""""""~-. \\`.
/// .'//.-" `-. | .-' "-.\\`.
/// .'//______.============-.. \ | / ..-============.______\\`.
/// .'______________________________\|/______________________________`.
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int MAXN=5e4+5;
int read()
{
int sum=0,flag=1;
char c;
for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=-1;
for(;c>='0'&&c<='9';c=getchar())sum=(sum<<1)+(sum<<3)+c-'0';
return sum*flag;
}
int n,L,op,R,c,num,block,be[MAXN],p[MAXN],a[MAXN],l[MAXN],r[MAXN];
int sum[MAXN];
int f[MAXN];
void build()
{
num=n/block;
if(n%block) num++;
rep(i,1,num)
{
l[i]=(i-1)*block+1;
r[i]=i*block;
}
r[num]=n;
}
void ask()
{
int ans=0;
if(be[L]==be[R]) rep(i,L,R) ans+=a[i];
else
{
rep(i,L,r[be[L]]) ans+=a[i];
rep(i,l[be[R]],R) ans+=a[i];
rep(i,be[L]+1,be[R]-1) ans+=sum[i];
}
printf("%d\n",ans);
}
void add()
{
if(be[L]==be[R]) rep(i,L,R) sum[be[L]]-=a[i],a[i]=sqrt(a[i]),sum[be[L]]+=a[i];
else
{
rep(i,L,r[be[L]]) sum[be[L]]-=a[i],a[i]=sqrt(a[i]),sum[be[L]]+=a[i];
rep(i,l[be[R]],R) sum[be[R]]-=a[i],a[i]=sqrt(a[i]),sum[be[R]]+=a[i];
rep(i,be[L]+1,be[R]-1)
{
if(f[i]) continue;
f[i]=1;sum[i]=0;
rep(j,l[i],r[i])
{
a[j]=sqrt(a[j]),sum[i]+=a[j];
if (a[j]>1) f[i]=0;
}
}
}
}
void init()
{
n=read();
block=sqrt(n);
rep(i,1,n) a[i]=read(),be[i]=(i-1)/block+1,sum[be[i]]+=a[i];
build();
rep(i,1,n)
{
op=read();L=read();R=read();c=read();
if(op) ask();
else add();
}
}
int main()
{
init();
return 0;
}