题解:P13983 数列分块入门 8
-
对于左右散块,我们下放并清空左右散块的懒标记,其中每有一个元素为
k ,答案就加1 。然后把左右散块的部分全赋值成k 。 -
对于每个整块,如果这个块有懒标记,若懒标记为
k ,则答案加块长,然后把懒标记赋为k 。否则遍历整个块,答案累加其中为k 的元素的个数,然后把所有元素和这个块的懒标记改为k 。
复杂度
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+1;
int n,cnt,q,x,y,k,a[N],bel[N],L[N],R[N],lz[N],blo;
void build(int n){
blo=sqrt(n);
cnt=(n+blo-1)/blo;
for(int i=1;i<=cnt;i++){
L[i]=(i-1)*blo+1;
R[i]=i*blo;
}
R[cnt]=n;
for(int i=1;i<=n;i++) bel[i]=(i-1)/blo+1;
memset(lz,-1,sizeof lz);
}
void upd(int x){
if(lz[x]==-1) return;
for(int i=L[x];i<=R[x];i++) a[i]=lz[x];
lz[x]=-1;
}
int qsum(int x,int y,int k){
int ans=0;
if(bel[x]==bel[y]){
upd(bel[x]);
for(int i=x;i<=y;i++){
if(a[i]!=k) a[i]=k;
else ans++;
}
return ans;
}
upd(bel[x]);
for(int i=x;i<=R[bel[x]];i++){
if(a[i]!=k) a[i]=k;
else ans++;
}
upd(bel[y]);
for(int i=L[bel[y]];i<=y;i++){
if(a[i]!=k) a[i]=k;
else ans++;
}
for(int i=bel[x]+1;i<bel[y];i++){
if(lz[i]!=-1){
if(lz[i]!=k) lz[i]=k;
else ans+=blo;
}
else{
for(int j=L[i];j<=R[i];j++){
if(a[j]!=k) a[j]=k;
else ans++;
}
lz[i]=k;
}
}
return ans;
}
signed main(){
cin>>n;
q=n;
for(int i=1;i<=n;i++) cin>>a[i];
build(n);
while(q--){
cin>>x>>y>>k;
cout<<qsum(x,y,k)<<endl;
}
}