题目大意:
给你一个长度为$n(nleq50000)$的序列$A(0leq A_i<2^{31})$,支持进行以下两种操作:
1.将区间$[l,r]$中所有数开方;
2.询问区间$[l,r]$的和。
思路:
分块。
因为当一个区间内的所有$A_i$都$leq1$时,操作1对答案没有影响,因此我们可以记录每个区间是否还有操作的必要。如果还有大于$1$的数,就暴力进行操作,否则跳过。易证每个区间最多开方4次。
1 #include<cmath> 2 #include<cstdio> 3 #include<cctype> 4 #include<algorithm> 5 typedef long long int64; 6 inline int getint() { 7 register char ch; 8 register bool neg=false; 9 while(!isdigit(ch=getchar())) if(ch=='-') neg=true; 10 register int x=ch^'0'; 11 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 12 return neg?-x:x; 13 } 14 const int N=50001; 15 int val[N],bel[N],begin[N],end[N],max[N]; 16 int64 sum[N]; 17 inline void modify(const int &l,const int &r,const int &c) { 18 if(bel[l]==bel[r]) { 19 for(register int i=l;i<=r;i++) val[i]=sqrt(val[i]); 20 sum[bel[l]]=max[bel[l]]=0; 21 for(register int i=begin[bel[l]];i<=end[bel[l]];i++) { 22 sum[bel[l]]+=val[i]; 23 max[bel[l]]=std::max(max[bel[l]],val[i]); 24 } 25 return; 26 } 27 for(register int i=l;bel[i]==bel[l];i++) val[i]=sqrt(val[i]); 28 for(register int i=r;bel[i]==bel[r];i--) val[i]=sqrt(val[i]); 29 for(register int i=bel[l]+1;i<bel[r];i++) { 30 if(max[i]==1) continue; 31 for(register int j=begin[i];j<=end[i];j++) val[j]=sqrt(val[j]); 32 } 33 for(register int i=bel[l];i<=bel[r];i++) { 34 if(max[i]==1) continue; 35 sum[i]=max[i]=0; 36 for(register int j=begin[i];j<=end[i];j++) { 37 sum[i]+=val[j]; 38 max[i]=std::max(max[i],val[j]); 39 } 40 } 41 } 42 inline int64 query(const int &l,const int &r) { 43 int64 ret=0; 44 if(bel[l]==bel[r]) { 45 for(register int i=l;i<=r;i++) ret+=val[i]; 46 return ret; 47 } 48 for(register int i=l;bel[i]==bel[l];i++) ret+=val[i]; 49 for(register int i=r;bel[i]==bel[r];i--) ret+=val[i]; 50 for(register int i=bel[l]+1;i<bel[r];i++) ret+=sum[i]; 51 return ret; 52 } 53 int main() { 54 const int n=getint(),block=sqrt(n); 55 for(register int i=1;i<=n;i++) { 56 val[i]=getint(); 57 bel[i]=i/block; 58 if(!begin[bel[i]]) begin[bel[i]]=i; 59 end[bel[i]]=i; 60 sum[bel[i]]+=val[i]; 61 max[bel[i]]=std::max(max[bel[i]],val[i]); 62 } 63 for(register int i=0;i<n;i++) { 64 const int opt=getint(),l=getint(),r=getint(),c=getint(); 65 if(opt) { 66 printf("%lld ",query(l,r)); 67 } else { 68 modify(l,r,c); 69 } 70 } 71 return 0; 72 }