https://vjudge.net/problem/HDU-4391
题目大意:给出
n
n
n面墙的初始颜色,
m
m
m个询问
(
a
,
l
,
r
,
z
)
(a,l,r,z)
(a,l,r,z),如果
a
=
1
a=1
a=1,表示把
[
l
,
r
]
[l,r]
[l,r]的所有墙染成
z
z
z,如果
a
=
2
a=2
a=2,表示查询
[
l
,
r
]
[l,r]
[l,r]的颜色为
z
z
z的墙的数量。
思路:分块 + + +哈希,没敢用 m a p map map,感觉可能会超时(实际上并不会)。思路其实挺简单的,和线段树的思想一样,搞一个 l a z y lazy lazy数组,用来维护一整块的信息,其它情况就通过 u n o r d e r e d _ m a p unordered\_map unordered_map来查询。每次修改操作,中间的块可以直接改 l a z y lazy lazy,两侧暴力修改,如果之前已经打上了 l a z y lazy lazy标记则需要 p u s h _ d o w n push\_down push_down操作。查询也是,中间的块先看 l a z y lazy lazy标记是否等于要查询的值,不相等的话通过哈希表查询,两侧暴力查询。注意查询时不要直接使用下标,如果颜色不存在的话会造成空间浪费,建议使用 f i n d find find函数。其他操作中对消失的颜色进行清空就行了。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n,m;
int a[maxn],pos[maxn],l[400],r[400],lazy[400];
unordered_map<int,int> col[400];//记录某一块某种颜色的数量
inline void down(int idx)
{
for(int i=l[idx];i<=r[idx];i++)
a[i]=lazy[idx];
col[idx].clear();
col[idx][lazy[idx]]=r[idx]-l[idx]+1;
lazy[idx]=-1;
}
inline void update(int ll,int rr,int v)
{
int posl=pos[ll],posr=pos[rr];
if(posl==posr)
{
if(lazy[posl]!=-1)
down(posl);
for(int i=ll;i<=rr;i++)
{
if(--col[posl][a[i]]==0)
col[posl].erase(a[i]);
a[i]=v;
}
col[posl][v]+=rr-ll+1;
}
else
{
if(lazy[posl]!=-1)
down(posl);
for(int i=ll;i<=r[posl];i++)
{
if(--col[posl][a[i]]==0)
col[posl].erase(a[i]);
a[i]=v;
}
col[posl][v]+=r[posl]-ll+1;
if(lazy[posr]!=-1)
down(posr);
for(int i=l[posr];i<=rr;i++)
{
if(--col[posr][a[i]]==0)
col[posr].erase(a[i]);
a[i]=v;
}
col[posr][v]+=rr-l[posr]+1;
for(int i=posl+1;i<posr;i++)
lazy[i]=v;
}
}
inline int query(int ll,int rr,int v)
{
int posl=pos[ll],posr=pos[rr],ans=0;
if(posl==posr)
{
if(lazy[posl]!=-1)
down(posl);
for(int i=ll;i<=rr;i++)
if(a[i]==v)
++ans;
}
else
{
if(lazy[posl]!=-1)
down(posl);
for(int i=ll;i<=r[posl];i++)
if(a[i]==v)
++ans;
if(lazy[posr]!=-1)
down(posr);
for(int i=l[posr];i<=rr;i++)
if(a[i]==v)
++ans;
for(int i=posl+1;i<posr;i++)
{
if(lazy[i]==v)
ans+=r[i]-l[i]+1;
else if(lazy[i]==-1&&col[i].find(v)!=col[i].end())
ans+=col[i][v];
}
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int dis=sqrt(n);
int num=ceil(n*1.0/dis);
for(int i=1;i<=num;i++)
l[i]=(i-1)*dis+1,r[i]=i*dis,lazy[i]=-1,col[i].clear();
r[num]=n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pos[i]=(i-1)/dis+1;
++col[pos[i]][a[i]];
}
int op,l,r,v;
while(m--)
{
scanf("%d%d%d%d",&op,&l,&r,&v);
++l,++r;
if(op==1)
update(l,r,v);
else
printf("%d\n",query(l,r,v));
}
}
return 0;
}