【Pregunta Solución】 Riego CF1181D

Título

Portal

Dado MMM ciudades, una ciudad será seleccionada para realizar el concurso cada año, y la antiguaNNSituación de las competiciones celebradas en ciudades en N años. En los años siguientes, la competencia anual se realizará en la ciudad con menor número de competencias, si hay muchas ciudades con menor número de veces, la competencia se realizará en la ciudad con menor número. Ahora daQQQ preguntas, cada vez que le pregunto aKK¿En qué ciudad se celebrará la competición en el año K ?

análisis

Debido a hábitos personales, ponga nn en el títulon ymmm significa intercambio.

Podemos abstraer el problema en nnn rectángulos con el mismo ancho y diferentes alturas, dada la altura inicial, cada vez que se selecciona el rectángulo más corto con el número más pequeño, y su altura es +1, y luego esta operación se repite continuamente, y la respuesta esKKEl número del rectángulo seleccionado K veces.

Vemos que tenemos que elegir el número más pequeño, así que no dudamos en ordenar primero. (Secuencia primero en caso de problemas)

Entonces podemos convertir el problema original en la siguiente figura:

VLzwKs.png

Descubrimos que varios rectángulos de la misma altura formarían una "plataforma". Así que piensa en cómo encontrar esta "plataforma".

Si saco una sección de "plataformas" por separado, debido a la misma altura, el orden en el que se seleccionan se debe ordenar por número y formar un círculo. Entonces, si quiero solicitar kk sobre la base de esta plataformak opciones, entonces lo que estamos buscando es el númeroken este segmento de la plataforma% lenk \% lenk % l e n es pequeño (dondelen lenl e n es la longitud de la plataforma, y ​​sik% len = 0 k \% len = 0k % l e n=0 , luego el que tiene el número más alto).

Entonces el número kk en esta plataforma de búsquedaLas operaciones con k pequeña se puedenmantenerutilizando el árbol debalance del árbol delsegmento de línea ponderado.


Desafortunadamente, obviamente tenemos más de una plataforma en nuestro problema, por lo que consideramos "llenar el pozo" de menor a mayor. Roba una foto de la solución oficial .

Para la conveniencia del procesamiento, tomamos la consulta fuera de línea y seguimos kkSe ordena el tamaño de k (es decir, el orden de prioridad).

VOSmd0.png

Por ejemplo, en esta imagen, los primeros tres rectángulos forman dos plataformas, luego encontramos la altura más alta {2, 5} \ {2,5 \}{ 2 ,5 } no estará contra3 33 tiene un impacto, tienes que esperar hasta3 33 alcance{2, 5} \ {2,5 \}{ 2 ,5 } se verá afectado después de la altura. Entonces podemos poner con seguridad3 33 completa{2, 5} \ {2,5 \}{ 2 ,5 } altura, luego pon3 33 Únase a la plataforma para formar{2, 3, 5} \ {2,3,5 \}{ 2 ,3 ,5 } Tal plataforma. Obviamente, después de llenar el pozo, todas las plataformas son prefijos de la secuencia original. En el proceso de llenado del pozo, se pueden responder algunas consultas, por lo que la respuesta se basa en la naturaleza de la plataforma. Al mismo tiempo, también necesitamos insertar los elementos recién agregados a la plataforma en el árbol del segmento de la línea de peso para la siguiente consulta.


Detalles de implementacion

Al procesar la plataforma y la consulta, se puede grabar un puntero respectivamente para indicar qué rectángulo o consulta se está procesando actualmente. Al mismo tiempo mantener un ahora ahoran o w significa que se han realizado varias selecciones actualmente (el valor inicial es el número de operaciones dado). Luego, para el rectángulo, se encuentra una plataforma hacia atrás cada vez, y el número del rectángulo en la plataforma se inserta en el árbol del segmento de la línea de peso en el proceso. Luego enumere la consulta hacia atrás, si la actualahora ahoran o w más el número de operaciones necesarias para la próxima plataforma para ser llenado es mayor que la consulta, a continuación, esta consulta se puede responder en este relleno hoyo, entonces la respuesta que se obtiene mediante la consulta en el árbol de segmento de línea ponderada. Finalmenteahora ahoraN o W se suma el número de operaciones requeridas para llenar el hoyo.

la complejidad

Ambos punteros se escanean linealmente, por lo que la parte de consulta de procesamiento es O ((n + q) logn) O ((n + q) logn)O ( ( n+q ) l o g n ) , porque la clasificación anterior requiereO (nlogn) O (nlogn)O ( n l o g n ) tiempo, por lo que la complejidad total esO ((n + q) logn) O ((n + q) logn)O ( ( n+q ) l o g n )

Código

#include <bits/stdc++.h>
#define ll long long
#define MAX 500005
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
#define mid ((l+r)>>1)
using namespace std;

namespace sgt{
    
    
    int s[MAX*4];

    void push_up(int p){
    
    
        s[p] = s[lc(p)]+s[rc(p)];
    }

    void update(int p, int l, int r, int u, int k){
    
    
        if(l == r){
    
    
            s[p] += k;
            return;
        }
        if(mid >= u) update(lc(p), l, mid, u, k);
        else update(rc(p), mid+1, r, u, k);
        push_up(p);
    }

    int query(int p, int l, int r, int k){
    
    
        if(l == r) return l;
        if(s[lc(p)] >= k){
    
    
            return query(lc(p), l, mid, k);
        }
        else return query(rc(p), mid+1, r, k-s[lc(p)]);
    }
}
//以上权值线段树模板

struct ask{
    
    		//询问离线
    ll k, id;
    friend bool operator <(ask a, ask b){
    
    
        return a.k < b.k;
    }
}q[MAX];

struct city{
    
    		//矩形
    ll h, id;

    friend bool operator <(city a, city b){
    
    
        if(a.h == b.h) return a.id < b.id;
        return a.h < b.h;
    }
}a[MAX];

int n, m;
ll Q, now, p, p1, p2, ans[MAX];

int main()
{
    
    
    cin >> m >> n >> Q;
    for(int i = 1; i <= n; ++i){
    
    
        a[i].id = i;
    }
    ll x;
    for(int i = 1; i <= m; ++i){
    
    
        scanf("%lld", &x);
        a[x].h++;
    }
    sort(a+1, a+n+1);
    for(int i = 1; i <= Q; ++i){
    
    
        scanf("%lld", &q[i].k);
        q[i].id = i;
    }
    sort(q+1, q+Q+1);
    //初始化:排序、离线

    p1 = p2 = 1;
    now = m;
    while(p1 <= n){
    
    
        p = p1;
        while(a[p].h == a[p1].h){
    
    		//向后找平台,并插入到权值线段树中
            sgt::update(1, 1, n, a[p].id, 1);
            p++;
        }
        while(now+(a[p].h-a[p1].h)*(p-1) >= q[p2].k){
    
    		//处理在这次填坑范围内的询问
            ll t = (q[p2].k-now)%(p-1);
            if(!t) t = p-1;
            ans[q[p2].id] = sgt::query(1, 1, n, t);
            p2++;
        }
        now += (a[p].h-a[p1].h)*(p-1);		//累加操作次数
        p1 = p;			//下一次平台的开始
    }
    for(int i = 1; i <= Q; ++i){
    
    
        //可能还有一些询问没有处理,但此时所有矩形都已形成一个平台,直接回答,甚至不需要权值线段树
        if(!ans[q[i].id]){
    
    
            ll t = (q[i].k-now)%n;
            if(!t) t = n;
            ans[q[i].id] = t;
        }
    }
    for(int i = 1; i <= Q; ++i){
    
    
        printf("%lld\n", ans[i]);
    }

    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/qq_30115697/article/details/92803851
Recomendado
Clasificación