直接放代码吧,我实在找不着错了(太蒻)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<map>
using namespace std;
#define MAXN 100010
#define ll long long
#define L(x) x<<1
#define R(x) x<<1|1
int n,m;
ll data[MAXN];
ll tresum[MAXN*4];
ll tremax[MAXN*4];
//由于一个数开根号后很快会变为1,所以可以判断开根号的值是否为1来减少开根号的次数(开到0会需要很多次)
//所以用一个新的数组来记录开根号后的值
int read()
{
char ch;
while((ch=getchar())>'9' || (ch<'0'));
int rs=ch-'0';
while((ch=getchar())<='9' && (ch>='0'))
rs=rs*10+ch-'0';
return rs;
}
void pushup(int x)
{
tresum[x]=tresum[L(x)]+tresum[R(x)];
tremax[x]=max(tremax[L(x)],tremax[R(x)]);
}
void build(int k,int l,int r)
{
if(l==r)
{
tresum[k]=tremax[k]=data[l];
return;
}
int mid=(l+r)/2;
build(L(k),l,mid);
build(R(k),mid+1,r);
pushup(k);
}
void change(int k,int l,int r,int x,ll v)
{
if(l==r)
{
tresum[k]=(long long)sqrt(tresum[k]);
tremax[k]=(long long)sqrt(tremax[k]);
return ;
}
if(tremax[k]<=1)
return ;
int mid=(l+r)/2;
if(mid>=x)
change(L(k),l,mid,x,v);
if(mid<v)
change(R(k),mid+1,r,x,v);
pushup(k);
}
ll query(int k,int l,int r,int x,int y)
{
if(y<l || x>r) //区间[x,y]与区间[l,r]无交集,则return
return 0;
if(x<=l && r<=y) //区间[l,r]完全在区间[x,y]内
return tresum[k]; //返回已经维护的值
int mid=(l+r)/2;
ll res=0;
if(mid>=x)
res=query(L(k),l,mid,x,y);
if(mid<y)
res+=query(R(k),mid+1,r,x,y);
return res;
}
int main()
{
memset(tresum,0,sizeof(tresum));
memset(tremax,0,sizeof(tremax));
n=read();
for(int i=1;i<=n;i++)
data[i]=read();
m=read();
build(1,1,n);
for(int i=1;i<=m;i++)
{
int x,l,r;
x=read();
l=read();
r=read();
if(l>r)
swap(l,r);
if(x==0)
change(1,1,n,l,r);
if(x==1)
printf("%lld\n",query(1,1,n,l,r));
}
return 0;
}