版权声明:存在错误或者不清楚的地方还望指出 https://blog.csdn.net/hypHuangYanPing/article/details/82947128
/**
HDU 4391 Paint The Wall 分块HASH
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4391
区间计数+区间推平;
分块HASH+标记;
************tricks**********
map<>mp;时间复杂度 竟然被称为O(1);
vector维护升序 二分查log复杂度不可避免 感觉复杂度差不多呀;
估计是数据针对排序所需复杂度多了一个log;
*/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+7;
int n,m,blo,x[maxn],pos[maxn];
struct node{
int cls,sz;
map<int,int>mp;
}b[500];
void pushdown(int id){
if(b[id].cls!=-1){
for(int i=(id-1)*blo+1;i<=min(n,id*blo);i++) x[i]=b[id].cls;
b[id].mp.clear(),b[id].mp[b[id].cls]=b[id].sz;
b[id].cls=-1;
}
}
void update(int l,int r,int c){
for(int i=pos[l]+1;i<=pos[r]-1;i++) b[i].cls=c;
if(pos[l]!=pos[r]){
pushdown(pos[l]);pushdown(pos[r]);
for(int i=l;i<=pos[l]*blo;i++) b[pos[l]].mp[x[i]]--,b[pos[l]].mp[c]++,x[i]=c;
for(int i=(pos[r]-1)*blo+1;i<=r;i++) b[pos[r]].mp[x[i]]--,b[pos[r]].mp[c]++,x[i]=c;
}
else{
pushdown(pos[l]);
for(int i=l;i<=r;i++) b[pos[l]].mp[x[i]]--,b[pos[l]].mp[c]++,x[i]=c;
}
}
int query(int l,int r,int c){
int ans=0;
for(int i=pos[l]+1;i<=pos[r]-1;i++){
if(b[i].cls==c) ans+=b[i].sz;
else if(b[i].cls==-1&&b[i].mp.find(c)!=b[i].mp.end()) ans+=b[i].mp[c];
}
if(pos[l]!=pos[r]){
pushdown(pos[l]);pushdown(pos[r]);
for(int i=l;i<=pos[l]*blo;i++) ans+=(x[i]==c);
for(int i=(pos[r]-1)*blo+1;i<=r;i++)ans+=(x[i]==c);
}
else{
pushdown(pos[l]);
for(int i=l;i<=r;i++)ans+=(x[i]==c);
}
return ans;
}
int q,l,r,z;
int main(){
while(~scanf("%d %d",&n,&m)){
blo=(int)sqrt(n*1.0);
for(int i=1;i<=n;i++) pos[i]=(i-1)/blo+1;
for(int i=1;i<=pos[n];i++){
b[i].mp.clear();
b[i].cls=-1;
b[i].sz=min(i*blo,n)-(i-1)*blo;
}
for(int i=1;i<=n;i++) {
scanf("%d",&x[i]);
b[pos[i]].mp[x[i]]++;
}
while(m--){
scanf("%d %d %d %d",&q,&l,&r,&z);l++,r++;
if(q==1) update(l,r,z);
else printf("%d\n",query(l,r,z));
}
}
return 0;
}