题解:P13983 数列分块入门 8
做法
对于每一个块,开一个桶记录某个值出现的数量。对于修改操作,散块直接下放标记暴力修改,整块直接打
代码
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int N=3e5+5,BB=700;
int n,tot;
int a[N],b[N<<1],tag[N/BB+3],L[N/BB+3],R[N/BB+3],bel[N];
short cnt[N/BB+3][N<<1];
struct Query{
int l,r,c;
}q[N];
inline void pushdown(int i){
if(!tag[i]) return;
rep(j,L[i],R[i]) cnt[i][a[j]]=0,a[j]=tag[i];
cnt[i][tag[i]]=R[i]-L[i]+1,tag[i]=0;
}
inline void update(int l,int r,int x){
if(bel[l]==bel[r]){
pushdown(bel[l]);
rep(i,l,r) cnt[bel[i]][a[i]]--,cnt[bel[i]][x]++,a[i]=x;
return;
}
pushdown(bel[l]),pushdown(bel[r]);
rep(i,l,R[bel[l]]) cnt[bel[i]][a[i]]--,cnt[bel[i]][x]++,a[i]=x;
rep(i,L[bel[r]],r) cnt[bel[i]][a[i]]--,cnt[bel[i]][x]++,a[i]=x;
rep(i,bel[l]+1,bel[r]-1) tag[i]=x;
}
inline int query(int l,int r,int x){
int ans=0;
if(bel[l]==bel[r]){
pushdown(bel[l]);
rep(i,l,r) ans+=(a[i]==x);
return ans;
}
pushdown(bel[l]),pushdown(bel[r]);
rep(i,l,R[bel[l]]) ans+=(a[i]==x);
rep(i,L[bel[r]],r) ans+=(a[i]==x);
rep(i,bel[l]+1,bel[r]-1){
if(!tag[i]) ans+=cnt[i][x];
else if(tag[i]==x) ans+=(R[i]-L[i]+1);
}
return ans;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
rep(i,1,n) cin>>a[i],b[++tot]=a[i],bel[i]=i/BB;
rep(i,1,n){
cin>>q[i].l>>q[i].r>>q[i].c;
b[++tot]=q[i].c;
}
sort(b+1,b+tot+1);
tot=unique(b+1,b+tot+1)-b-1;
rep(i,1,n) a[i]=lower_bound(b+1,b+tot+1,a[i])-b,q[i].c=lower_bound(b+1,b+tot+1,q[i].c)-b,cnt[bel[i]][a[i]]++;
rep(i,1,n) if(!L[bel[i]]) L[bel[i]]=i;
for(int i=n;i>=1;--i) if(!R[bel[i]]) R[bel[i]]=i;
rep(i,1,n){
cout<<query(q[i].l,q[i].r,q[i].c)<<'\n';
update(q[i].l,q[i].r,q[i].c);
}
return 0;
}