题目链接
这道题其实和上帝造题的七分钟1没有什么关系,是一道线段树的题。
笔者是第一次看见区间整体开方的题,开始有点慌,结果发现并不难。通过计算,我们不难得出这道题最大可能有的数1e12只需要经过6次开方就可以变成接近1的数,我们又知道如果一个数等于1,那么它的开方永远还是1.
因此,我们又可以发现,这道题的数据只有1e5,是可以支持暴力修改的,只需要看这段区间最大值是否超过1.
所以,我们可以发现这道题就是一道线段树还不加lazy的暴力修改。但是由于笔者是个蒟蒻,读入优化写的是int类型硬是没查出来,结果交了十几遍五十分
特别注意:题目中会有l>r的情况,这要我们交换l和r
具体代码如下
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long p[100010];
struct node{
int l,r;
long long value;
}tree[400010];
inline long long read(){
long long s=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())s=(s<<3)+(s<<1)+(c^48);
return s*f;
}
inline void write(long long x){
if(x<0){putchar('-');x=-x;}
if(x>9) write(x/10);
putchar(x%10+'0');
}
void build(int l,int r,int number){
if(l==r){
tree[number].value=p[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,number<<1);
build(mid+1,r,number<<1|1);
tree[number].value=tree[number<<1].value+tree[number<<1|1].value;
}
void in(int l,int r,int number,int ll,int rr){
if(r-l+1==tree[number].value)return;
if(l==r){
tree[number].value=floor(sqrt(tree[number].value));
return;
}
int mid=(l+r)>>1;
if(ll<=mid)in(l,mid,number<<1,ll,rr);
if(rr>mid)in(mid+1,r,number<<1|1,ll,rr);
tree[number].value=tree[number<<1].value+tree[number<<1|1].value;
}
long long query(int l,int r,int number,int ll,int rr){
if(ll<=l&&r<=rr){
return tree[number].value;
}
long long s=0;
int mid=(l+r)>>1;
if(ll<=mid)s+=query(l,mid,number<<1,ll,rr);
if(rr>mid)s+=query(mid+1,r,number<<1|1,ll,rr);
return s;
}
int main(){
n=read();
for(int i=1;i<=n;i++)p[i]=read();
build(1,n,1);
m=read();
for(int i=1;i<=m;i++){
int opt=read(),x=read(),y=read();
if(x>y)swap(x,y); //注意要交换,否则就RE
if(opt){
long long ans=query(1,n,1,x,y);
write(ans);putchar('\n');
}
else in(1,n,1,x,y);
}
return 0;
}