虽然说这题暴力有95,
但正解的想法还是很值得学习的
对于一个时刻更新的区间,且这个区间有许多要更新的值
使用线段树的话,在更新子树时复杂度会很高
这里采用map+分块的方法 复杂度约为O(nloglogn)
#include<cstdio>
#include<cmath>
#include<map>
using namespace std;
#define M 100005
#define N 330
#define yzk is not yz_gay
//分块+map离散
struct node{
int col;
map<int,int>mp;
node(){col=-1;}
}B[N];
int A[M],m;
void change(int k){
if(B[k].col==-1)return;
for(int i=k*m;i<k*m+m;i++)A[i]=B[k].col;
B[k].col=-1;
}
void update(int l,int r,int col){
int L=l/m,R=r/m;
if(L==R){
change(L);
for(int i=l;i<=r;i++){
B[L].mp[A[i]]--;
A[i]=col;
B[L].mp[A[i]]++;
}
return;
}
change(L);
for(int i=l;i<L*m+m;i++){
B[L].mp[A[i]]--;
A[i]=col;
B[L].mp[A[i]]++;
}
for(int i=L+1;i<R;i++){
B[i].col=col;
B[i].mp.clear();
B[i].mp[col]=m;
}
change(R);
for(int i=R*m;i<=r;i++){
B[R].mp[A[i]]--;
A[i]=col;
B[R].mp[A[i]]++;
}
}
int query(int l,int r,int col){
int L=l/m,R=r/m,cnt=0;
if(L==R){
change(L);
for(int i=l;i<=r;i++)if(A[i]==col)cnt++;
return cnt;
}
change(L);
for(int i=l;i<L*m+m;i++)if(A[i]==col)cnt++;
for(int i=L+1;i<R;i++)cnt+=B[i].mp[col];
change(R);
for(int i=R*m;i<=r;i++)if(A[i]==col)cnt++;
return cnt;
}
int main(){
int n,q;
scanf("%d%d",&n,&q);
for(int i=0;i<n;i++)scanf("%d",&A[i]);
m=sqrt(n);
for(int i=0;i<n;i++)B[i/m].mp[A[i]]++;
while(q--){
int l,r,op,col;
scanf("%d %d %d %d",&op,&l,&r,&col);
if(op==1)update(l,r,col);
else printf("%d\n",query(l,r,col));
}
return 0;
}