P13980 数列分块入门 5 题解
思路
一个数
暴力处理每次有意义的开方,一共也就
实现
写线段树。
#include<stdio.h>
#include<math.h>
#define N 524288
#define lc ((i)<<1|1)
#define rc ((i)+1<<1)
inline char nc()
{
static char*l,*r,buf[99999];
return l==r&&(r=(l=buf)+fread(buf,1,99999,stdin),l==r)?EOF:*l++;
}
inline void read(int&x)
{
char c=nc();for(;c<'0'||'9'<c;c=nc());
for(x=0;'0'<=c&&c<='9';x=(x<<3)+(x<<1)+(c^48),c=nc());
}
int n,maxn[N<<1];long long sum[N<<1];
inline int max(int x,int y){return x>y?x:y;}
inline void build(int i,int l,int r)
{
if(l==r){read(maxn[i]);sum[i]=maxn[i];return;}
int mid=l+r>>1;build(lc,l,mid);build(rc,mid+1,r);
sum[i]=sum[lc]+sum[rc];maxn[i]=max(maxn[lc],maxn[rc]);
}
inline void work(int i,int l,int r,int ql,int qr)
{
if(qr<l||r<ql||maxn[i]<=1)return;
if(l==r){maxn[i]=sum[i]=sqrt(maxn[i]);return;}
int mid=l+r>>1;work(lc,l,mid,ql,qr);work(rc,mid+1,r,ql,qr);
sum[i]=sum[lc]+sum[rc];maxn[i]=max(maxn[lc],maxn[rc]);
}
inline long long qry(int i,int l,int r,int ql,int qr)
{
if(qr<l||r<ql)return 0;
if(ql<=l&&r<=qr)return sum[i];
int mid=l+r>>1;return qry(lc,l,mid,ql,qr)+qry(rc,mid+1,r,ql,qr);
}
main()
{
read(n);build(0,0,n-1);
for(int i=n,o,l,r;i--;)if(read(o),read(l),read(r),--l,--r,o)
printf("%lld\n",qry(0,0,n-1,l,r));
else work(0,0,n-1,l,r);
}