Mantenga una matriz b, que almacena el color (b []. C) y la posición (b []. Id) de cada punto, y luego ordénelo,
Si lo modifica, busque la posición de X y X + 1 y luego b, simplemente intercambie sus identificadores (porque ciertamente no afectará el orden relativo de los mismos colores).
Para la consulta, encuentre el intervalo continuo del color C en by divida L y R en dos.
Algunos pequeños detalles se pueden ver en las notas.
programa
#include <cstdio>#include <algorithm>#define N 400005usingnamespacestd;
struct zzk{
int c,id;} b[N];
bool cmp(zzk x,zzk y){ //把相同颜色的堆在一起(颜色也递增),然后相同颜色的一堆中编号递增以便二分 if (x.c==y.c) return x.id<y.id;
return x.c<y.c;
}
int n,m,a[N];
int ef_c(int c){ //二分 为颜色 c 最后一个位置 if (!c) return0;
int l,r,mid,ret=0;
for (l=1,r=n; l<=r; ){
mid=l+r>>1;
if (b[mid].c<=c && b[mid-1].c<=c){ret=mid,l=mid+1; continue;}
r=mid-1;
}
return ret;
}
int ef_I(int l,int r,int I){ //id I 在区间 [l,r] 在哪里(左偏) int mid,ret=l;
for (; l<=r; ){
mid=l+r>>1;
if (b[mid].id<=I){ret=mid,l=mid+1; continue;}
r=mid-1;
}
return ret;
}
void option_1(int L,int R,int C){ //询问 [L,R] 中的 C int lc,rc,st,ed;
lc=ef_c(C-1)+1,rc=ef_c(C); //颜色C在 b 中的区间
st=ef_I(lc,rc,L),ed=ef_I(lc,rc,R); //找到 L,R 在区间包了哪些数 if (b[st].id>=L && b[st].id<=R && b[st].c==C) st--; //处理一下细节 printf("%d\n",ed-st);
}
void option_2(int X){ //修改 X int C1=a[X],C2=a[X+1],lc,rc,kk1,kk2;
lc=ef_c(C1-1)+1,rc=ef_c(C1),kk1=ef_I(lc,rc,X); //找到 a[X] 在 b 中对应位置
lc=ef_c(C2-1)+1,rc=ef_c(C2),kk2=ef_I(lc,rc,X+1); //找到 a[X+1] 在 b 中对应位置
swap(b[kk1].id,b[kk2].id); //位置交换
swap(a[X],a[X+1]);
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++) scanf("%d",&a[i]),b[i].id=i,b[i].c=a[i];
sort(b+1,b+n+1,cmp);
for (int k1,k2,k3,k; m--; ){
scanf("%d",&k);
if (k==1 && scanf("%d%d%d",&k1,&k2,&k3)){
option_1(k1,k2,k3);
}
if (k==2 && scanf("%d",&k1)){
if (a[k1]==a[k1+1]) continue;
option_2(k1);
}
}
}
rápido
Por supuesto, existen muchos métodos de estructura de datos para este problema, como árboles de segmentos de línea persistentes, y también puede practicar.