#权值线段树#洛谷 3939 数颜色
分析
考虑按照颜色建权值线段树,交换直接删除再添加就可以了
如果离散化要特判不过其实不需要离散化
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=300011;
int n,Q,w[N<<5],ls[N<<5],cnt,rs[N<<5],rt[N],a[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline void update(int &k,int l,int r,int x,int y){
if (!k) k=++cnt; w[k]+=y;
if (l==r) return;
rr int mid=(l+r)>>1;
if (x<=mid) update(ls[k],l,mid,x,y);
else update(rs[k],mid+1,r,x,y);
}
inline signed query(int k,int l,int r,int x,int y){
if (!k) return 0;
if (l==x&&r==y) return w[k];
rr int mid=(l+r)>>1;
if (y<=mid) return query(ls[k],l,mid,x,y);
else if (x>mid) return query(rs[k],mid+1,r,x,y);
else return query(ls[k],l,mid,x,mid)+query(rs[k],mid+1,r,mid+1,y);
}
signed main(){
n=iut(); Q=iut();
for (rr int i=1;i<=n;++i) update(rt[a[i]=iut()],1,n,i,1);
while (Q--){
rr int o=iut();
if (o==1){
rr int l=iut(),r=iut(),z=iut();
print(query(rt[z],1,n,l,r)),putchar(10);
}else{
rr int x=iut();
if (a[x]==a[x+1]) continue;
update(rt[a[x]],1,n,x,-1);
update(rt[a[x+1]],1,n,x+1,-1);
update(rt[a[x]],1,n,x+1,1);
update(rt[a[x+1]],1,n,x,1);
a[x]^=a[x+1],a[x+1]^=a[x],a[x]^=a[x+1];
}
}
return 0;
}