分块入门题5:
给[L,R]取开方,一个数字最多被取开方6次,那么一个块内有需要开方的时候才对这个块取开方,那么最多6*n*sqrt(n)次,分块直接写
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
int l[5500],r[5500],belong[105000];
int q1[105000],q2[105000];
int is[5005],mark[5005];
int n,block,num;
ll sum1[5005];
void build(){
double f1=n;
block=sqrt(f1);
if(block==0)block=1;
num=n/block;if(n%block!=0)num++;
int i;
for(i=1;i<=n;i++){
belong[i]=(i-1)/block+1;
is[belong[i]]+=6; //is表示的是这个里面的块数,6次就不再sqrt了
sum1[belong[i]]+=q1[i];
}
for(i=1;i<=num;i++){ //i表示这一个块l[i],r[i]
l[i]=(i-1)*block+1;
r[i]=min(n,i*block); //每个block个边界,是包括的
}//这里为第i块的左区间与右区间
}
int modify(int x,int y,int t){
int i,res=0,ans=0;
if(belong[x]==belong[y]){
for(i=x;i<=y;i++){
sum1[belong[i]]-=q1[i]-sqrt(q1[i]);
q1[i]=sqrt(q1[i]);
if(q2[i]<6){//最多修改6次
q2[i]++;
is[belong[i]]--;
}
}
if(is[belong[x]]==0)mark[x]=1;
}else{
for(i=x;i<=r[belong[x]];i++){
sum1[belong[i]]-=q1[i]-sqrt(q1[i]);
q1[i]=sqrt(q1[i]);
if(q2[i]<6){//最多修改5次
q2[i]++;
is[belong[i]]--;
}
}
if(is[belong[x]]==0)mark[x]=1;
for(i=l[belong[y]];i<=y;i++){
sum1[belong[i]]-=q1[i]-sqrt(q1[i]);
q1[i]=sqrt(q1[i]);
if(q2[i]<6){//最多修改5次
q2[i]++;
is[belong[i]]--;
}
}
if(is[belong[y]]==0)mark[y]=1;
int left1,right1,mid1;
for(i=belong[x]+1;i<belong[y];i++){//
if(mark[i]==0){
for(int j=l[i];j<=r[i];j++){
sum1[i]-=q1[j]-sqrt(q1[j]);
q1[j]=sqrt(q1[j]);
if(q2[j]<6){//最多修改5次
q2[j]++;
is[i]--;
}
}
if(is[i]==0)mark[i]=1;
}
}
}
}
int res;
ll cnt;
int find1(int x,int y){
int i,ans;
if(belong[x]==belong[y]){
for(i=x;i<=y;i++)
cnt+=q1[i];
}else{
for(i=x;i<=r[belong[x]];i++)
cnt+=q1[i];
for(i=l[belong[y]];i<=y;i++)
cnt+=q1[i];
int left1,right1,mid1;
for(i=belong[x]+1;i<belong[y];i++){
cnt+=sum1[i];
}
}
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out1.txt","w",stdout);
int i,k,j,f1,f2,f3,f4,t1,t2,t3,t4,l2,m;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&q1[i]);
build();
for(i=1;i<=n;i++){
scanf("%d %d %d %d",&t1,&t2,&t3,&t4);
if(t1==0){ //查询[t2,t3]全部+t4
modify(t2,t3,t4);
}else{
cnt=0;
find1(t2,t3); //比其小的最大元素
printf("%d\n",cnt);
}
}
return 0;
}