Cupcake Bonuses (UCF Local Programming Contest 2018 E, dfs order + line segment tree)

1. Title link:

Cupcake Bonuses

2. The main idea of ​​the topic:

There is an employee initially, and there are four operations:

1 i: Give one employee to the i-th employee.

2 im: Set the salary coefficient of the i-th employee to m.

3 ib: The salary of the i-th employee and all its subordinate funds is b, and the actual salary of each person is equal to the salary coefficient of the fund b * this person.

4 i: Query the actual salary currently received by the i-th employee.

3. Analysis:

This question can be directly violent. (When I saw the first reaction in the game, I saw the line segment tree in the dfs sequence. I played a fake question for my teammates for two hours, and finally there was no A...

The violent approach will not be written, and the line segment tree approach will be placed below.

It took a long time to sort out sexual dementia during the game.

4. Code implementation:

#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;
}

 

Guess you like

Origin blog.csdn.net/The___Flash/article/details/105116230