题解:分块。操作只有开方,一个数经历几次开方后就会变成1。暴力开方,flag[ ] 标记此块是否全被开方为1。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int n,block,cnt,flag[maxn];
long long sum[maxn],w[maxn];
int get(int x);
void update(int l,int r,int c);
long long check(int l,int r);
int main()
{
int i,op,l,r,c;
scanf("%d",&n);
block=sqrt(n);
if(n%block) cnt=n/block+1;
else cnt=n/block;
for(i=1;i<=n;i++)
{
scanf("%lld",&w[i]);
sum[get(i)]+=w[i];
}
for(i=0;i<n;i++)
{
scanf("%d%d%d%d",&op,&l,&r,&c);
if(op==0) update(l,r,c);
else printf("%lld
",check(l,r));
}
system("pause");
return 0;
}
int get(int x)
{return (x-1)/block+1;}
void update(int l,int r,int c)
{
int pre,end,k;
pre=get(l);end=get(r);
if(pre==end)
{
for(k=l;k<=r;k++)
{
sum[get(k)]-=w[k];
w[k]=sqrt(w[k]);
sum[get(k)]+=w[k];
}
}
else
{
for(k=l;k<=min(pre*block,n);k++)
{
sum[get(k)]-=w[k];
w[k]=sqrt(w[k]);
sum[get(k)]+=w[k];
}
for(k=(end-1)*block+1;k<=r;k++)
{
sum[get(k)]-=w[k];
w[k]=sqrt(w[k]);
sum[get(k)]+=w[k];
}
for(k=pre+1;k<end;k++)
{
if(flag[k]) continue;
else
{
flag[k]=1;
for(int j=(k-1)*block+1;j<=k*block;j++)
{
sum[k]-=w[j];
w[j]=sqrt(w[j]);
sum[k]+=w[j];
if(w[j]!=1) flag[k]=0;
}
}
}
}
}
long long check(int l,int r)
{
long long ans=0;
int pre,end,k,x;
pre=get(l);end=get(r);
if(pre==end)
{
for(k=l;k<=r;k++)
ans+=w[k];
}
else
{
for(k=l;k<=min(pre*block,n);k++) ans+=w[k];
for(k=(end-1)*block+1;k<=r;k++) ans+=w[k];
for(k=pre+1;k<end;k++)
{
if(flag[k]) ans+=block;
else ans+=sum[k];
}
}
return ans;
}
题解:分块。与数列分块入门5类似。若某块全为同一个值,则用flag[ ]标记,直接计算,反之,暴力统计。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int n,block,w[maxn],flag[maxn];
int get(int k)
{return (k-1)/block+1;}
void reset(int k);
int check(int l,int r,int c);
int main()
{
fill(flag,flag+maxn,-1);
int i,l,r,c;
scanf("%d",&n);
block=sqrt(n);
for(i=1;i<=n;i++) scanf("%d",&w[i]);
for(i=0;i<n;i++)
{
scanf("%d%d%d",&l,&r,&c);
printf("%d
",check(l,r,c));
}
system("pause");
return 0;
}
void reset(int k)
{
if(flag[k]==-1) return ;
for(int i=(k-1)*block+1;i<=min(k*block,n);i++)
w[i]=flag[k];
flag[k]=-1;
}
int check(int l,int r,int c)
{
int pre,end,k,ans=0;
pre=get(l);end=get(r);
reset(pre);
if(pre==end)
{
for(k=l;k<=r;k++)
{
if(w[k]==c) ans++;
else w[k]=c;
}
}
else
{
reset(end);
for(k=l;k<=min(pre*block,n);k++)
{
if(w[k]==c) ans++;
else w[k]=c;
}
for(k=(end-1)*block+1;k<=r;k++)
{
if(w[k]==c) ans++;
else w[k]=c;
}
for(k=pre+1;k<end;k++)
{
if(flag[k]!=-1)
{
if(flag[k]==c) ans+=block;
else flag[k]=c;
}
else
{
flag[k]=c;
for(int i=(k-1)*block+1;i<=k*block;i++)
{
if(w[i]==c) ans++;
else w[i]=c;
}
}
}
}
return ans;
}