Preguntas de codeforce brush (4)

CodeForces 1320C World of Darkraft: Battle for Azathoth

\ (n \) armas \ (m \) escudos, tanto las armas como los escudos tienen el valor de ataque correspondiente (valor de defensa) y el precio, y los monstruos \ (p \) , cada monstruo tiene defensa Valor, valor de ataque y cuánto dinero puedes obtener al matarlo. Solo puedes elegir un arma y un escudo, y preguntar cuánto dinero obtendrás más a través de la pelea (después de restar el costo de comprar armas y escudos).

Solución

La idea más simple es \ (O (nmp) \) , obviamente no. Como empiezas Si solo se considera una dimensión, después de clasificar las armas y los monstruos por separado, se puede resolver el sufijo de dos puntos. Ahora es unidimensional: los ataques de escudos y monstruos son un poco difíciles. Para cada arma, si la colección de monstruos que puede matar (solo el valor de ataque del arma es mayor que el valor de defensa del monstruo) es \ (S \) , entonces, ¿cómo encontrar la ganancia máxima en la colección \ (S \) ? ? Construye un árbol de segmentos de línea para mantener el retorno máximo del conjunto \ (S \) . Por cada monstruo agregado, si su valor de ataque es \ (x \) , actualiza el valor máximo de la parte mayor que \ (x \) Valor. Por ejemplo: deje que el escudo con \ (a [i]: = \) valor de defensa de \ (i \) en el conjunto S lo ayude a obtener el mayor beneficio, agregue un monstruo con valor de ataque de \ (x \) , Simplemente actualice: \ (a [x + 1] + = monedas, a [x + 2] + = monedas, ··· \) , y luego tome su valor máximo \ (max (a) \) es el conjunto \ (S \) La mayor ganancia.

Cuando los valores de defensa de escudo son los mismos, y sin duda la opción más económica que el escudo, que está en los logros de la función: ma[root] = max(ma[root], -b.price).

struct monster {
    int x, y, z;
    bool operator < (const monster o) const {
        return x < o.x;
    }
};

int n, m, p, cnt;
long long ma[1000005 * 4], laz[1000005 * 4];

void Build_Tree(int l, int r, int root, int pos, int x) {
    if ((l == r) && (l == pos)) {
        ma[root] = max(ma[root], (long long)-x);  // 坑点1
        return;
    }
    int mid = (l + r) >> 1;
    if (pos <= mid) Build_Tree(l, mid, root << 1, pos, x);
    else Build_Tree(mid + 1, r, (root << 1) + 1, pos, x);
    ma[root] = max(ma[root << 1], ma[(root << 1) + 1]);
}

void Push_down(int root) {
    laz[root << 1] += laz[root];
    laz[(root << 1) + 1] += laz[root];
    ma[(root << 1)] += laz[root];
    ma[(root << 1) + 1] += laz[root];
    laz[root] = 0;
}

void Update_Tree(int L, int R, int l, int r, int root, int coins) {
    if (L > R) return;         // 坑点2
    if (L <= l && r <= R) {
        ma[root] += coins;
        laz[root] += coins;
        return;
    }
    if (laz[root]) Push_down(root);
    int mid = (l + r) >> 1;
    if (L <= mid) Update_Tree(L, R, l, mid, root << 1, coins);
    if (R > mid) Update_Tree(L, R, mid  + 1, r, (root << 1) + 1, coins);
    ma[root] = max(ma[root << 1], ma[(root << 1) + 1]);
}

int main()
{

    scanf("%d %d %d", &n, &m, &p);

    vector<pair<int, int> > a(n), b(m);
    vector<struct monster > c(p);

    int length = 0;

    myfor(i, 0, n) scanf("%d %d", &a[i].first, &a[i].second);
    myfor(i, 0, m) scanf("%d %d", &b[i].first, &b[i].second), length = max(length, b[i].first);
    myfor(i, 0, p) scanf("%d %d %d", &c[i].x, &c[i].y, &c[i].z), length = max(length, c[i].y);


    sort(a.begin(), a.end());
    sort(c.begin(), c.end());

    myfor(i, 0, length * 4) ma[i] = -INF;
    myfor(i, 0, m) Build_Tree(1, length, 1, b[i].first, b[i].second);

    int index = 0;
    long long ans = -INF;

    myfor(i, 0, n) {
        while(index < p && c[index].x < a[i].first) {
            Update_Tree(c[index].y + 1, length, 1, length, 1, c[index].z);        // length = max(c.y), 所以可能会出现:c[index].y + 1 > length 
            index++;
        }
        ans = max(ans, ma[1] - a[i].second);
    }

    cout << ans << endl;
    return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/zgglj-com/p/12676739.html
Recomendado
Clasificación