Luogu-3939 (dos puntos)

tema

Color del número P3939

análisis

  • 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 400005
using namespace std;
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) return 0;
    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.

Supongo que te gusta

Origin blog.csdn.net/jackypigpig/article/details/78431047
Recomendado
Clasificación