Bonos de cupcakes (Concurso de programación local UCF 2018 E, pedido de dfs + árbol de segmento de línea)

1. Enlace de título:

Bonos de cupcakes

2. La idea principal del tema:

Inicialmente hay un empleado y hay cuatro operaciones:

1 i: Entregue un empleado al i-ésimo empleado.

2 im: establece el coeficiente salarial del i-ésimo empleado en m.

3 ib: El salario del i-ésimo empleado y todos sus fondos subordinados es b, y el salario real de cada persona es igual al coeficiente salarial del fondo b * esta persona.

4 i: Consultar el salario real que recibe actualmente el i-ésimo empleado.

3. Análisis:

Esta pregunta puede ser directamente violenta. (Cuando vi la primera reacción en el juego, vi el árbol del segmento de línea en la secuencia dfs. Jugué una pregunta falsa para mis compañeros de equipo durante dos horas, y finalmente no hubo A ...

El enfoque violento no se escribirá y el enfoque de árbol de segmento de línea se colocará debajo.

Me tomó mucho tiempo resolver la demencia sexual durante el juego.

4. Implementación del código:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)1e5;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;

int n, S;
struct qnode
{
    int a, b, c;
}query[M + 5];

int num, cnt;
vector <int> son[M + 5];
int st[M + 5], en[M + 5];

struct tnode
{
    int l, r; ll lzb;
}tree[M * 4 + 5];
ll m[M + 5], s[M + 5];

void dfs(int u)
{
    ++cnt;
    st[u] = cnt;
    for(auto x: son[u]) dfs(x);
    en[u] = cnt;
}

inline int lc(int k)    {return k<<1;}
inline int rc(int k)    {return k<<1|1;}

void push_down(int k)
{
    if(!tree[k].lzb)                   return;
    if(tree[lc(k)].l == tree[lc(k)].r) s[tree[lc(k)].l] += tree[k].lzb * m[tree[lc(k)].l];
    else                               tree[lc(k)].lzb += tree[k].lzb;
    if(tree[rc(k)].l == tree[rc(k)].r) s[tree[rc(k)].l] += tree[k].lzb * m[tree[rc(k)].l];
    else                               tree[rc(k)].lzb += tree[k].lzb;
    tree[k].lzb = 0;
}

void Build(int k, int l, int r)
{
    tree[k].l = l, tree[k].r = r;
    if(l == r)  return;
    int mid = (l + r) >> 1;
    Build(lc(k), l, mid);
    Build(rc(k), mid + 1, r);
}

void Update1(int k, int a, int b)
{
    if(tree[k].l == tree[k].r) {m[tree[k].l] = b; return;}
    push_down(k);
    int mid = (tree[k].l + tree[k].r) >> 1;
    if(a <= mid)    Update1(lc(k), a, b);
    else            Update1(rc(k), a, b);
}

void Update2(int k, int a, int b, int c)
{
    if(tree[k].l >= a && tree[k].r <= b)
    {
        if(tree[k].l == tree[k].r)  s[tree[k].l] += m[tree[k].l] * c;
        else tree[k].lzb += c;
        return;
    }
    push_down(k);
    int mid = (tree[k].l + tree[k].r) >> 1;
    if(a <= mid)    Update2(lc(k), a, b, c);
    if(mid < b)     Update2(rc(k), a, b, c);
}

ll Query(int k, int a)
{
    if(tree[k].l == tree[k].r)  return s[tree[k].l];
    push_down(k);
    int mid = (tree[k].l + tree[k].r) >> 1;
    if(a <= mid)    Query(lc(k), a);
    else            Query(rc(k), a);
}

int main()
{
    scanf("%d %d", &n, &S);
    num = 1;
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d %d", &query[i].a, &query[i].b);
        if(query[i].a == 2 ||query[i].a == 3)   scanf("%d", &query[i].c);
        if(query[i].a == 1) son[query[i].b].push_back(++num), query[i].b = num;
    }
    dfs(1); Build(1, 1, cnt);
    Update1(1, st[1], S);
    for(int i = 1; i <= n; ++i)
    {
        if(query[i].a == 1)      Update1(1, st[query[i].b], S);
        else if(query[i].a == 2) Update1(1, st[query[i].b], query[i].c);
        else if(query[i].a == 3) Update2(1, st[query[i].b], en[query[i].b], query[i].c);
        else if(query[i].a == 4) printf("%lld\n", Query(1, st[query[i].b]));
    }
    return 0;
}

 

Supongo que te gusta

Origin blog.csdn.net/The___Flash/article/details/105116230
Recomendado
Clasificación