配对堆 20pts 全 TLE 求助
查看原帖
配对堆 20pts 全 TLE 求助
655192
Tibrella楼主2023/5/28 17:09

如题,cin 和 cout 是快读实现的,没放出来

#define N 300005

using i64 = long long;

struct sakuya {
    i64 s;
    i64 id;
    i64 start;

    bool operator<(const sakuya& a) {
        return s < a.s;
    }
    bool operator>(const sakuya& a) {
        return s > a.s;
    }
};

struct Node {
    Node *child, *nex;
    sakuya val;
    i64 plus, mul;  // 加后乘

    Node() {
        mul = 1;
    }

    void push_down() {
        Node* c = child;
        val.s *= mul;
        val.s += plus;
        while (c->val.s != 0) {
            if (mul) {
                c->mul *= mul;
                c->plus *= plus;
            }
            if (plus) {
                c->plus += plus;
            }
            c = c->nex;
        }
        mul = 1, plus = 0;
    }
} space[N];

Node *tot = space + 1, *null = space;

Node* meld(Node* x, Node* y) {
    if (x == null)
        return y;
    else if (y == null)
        return x;
    x->push_down();
    y->push_down();
    if (x->val > y->val) {
        x->nex = y->child;
        y->child = x;
        return y;
    } else {
        y->nex = x->child;
        x->child = y;
        return x;
    }
}

Node* merge(Node* nod) {
    if (nod == null || nod->nex == null) return nod;
    Node *x = nod->nex, *y = nod->nex->nex;
    x->nex = nod->nex = null;
    x->push_down();
    y->push_down();
    nod->push_down();
    return meld(merge(y), meld(nod, x));
}

void push(Node*& root, sakuya val) {
    Node* y = ++tot;
    y->val = val;
    y->child = y->nex = null;
    if (root == null) {
        root = y;
        return;
    }
    root->push_down();
    root = meld(root, y);
}

void pop(Node*& root) {
    Node* t = merge(root->child);
    root->child = root->nex = null;
    root->mul = 1;
    root->plus = 0;
    root->val = { 0, 0, 0 };
    root = t;
}

i64 son[N], nex[N];  // 左儿子右兄弟
i64 op[N], val[N];
i64 hp[N];
Node* heap[N];
i64 kill[N], guard[N];
i64 dep[N];

i64 n, m;
i64 t1, t2, t3;

void dfs(int nod) {
    // if (heap[nod] == null) return;
    for (int to = son[nod]; to; to = nex[to]) {
        dep[to] = dep[nod] + 1;
        dfs(to);
        if (heap[to] != null) {
            heap[to]->child = merge(heap[to]->child);  // 多配对几次防止 push_down 复杂度爆炸
            heap[to]->push_down();                     // 标记下传
            heap[nod] = meld(heap[nod], heap[to]);     // 合并
            heap[nod]->child = merge(heap[nod]->child);
        }
    }
    heap[nod]->push_down();
    while (heap[nod] != null && heap[nod]->val.s < hp[nod]) {
        ++guard[nod];                                                    // 当前城池杀人 + 1
        kill[heap[nod]->val.id] = dep[heap[nod]->val.start] - dep[nod];  // 起点深度 - 终点深度
        pop(heap[nod]);
        heap[nod]->push_down();
    }
    // 添加标记
    if (op[nod]) {
        heap[nod]->mul *= val[nod];
        heap[nod]->plus *= val[nod];
    } else {
        heap[nod]->plus += val[nod];
    }
}

void last(Node* nod) {  // 统计最后一个堆的节点
    if (nod == null) return;
    kill[nod->val.id] = dep[nod->val.start];  // 起点深度 - 终点深度
    last(nod->nex);
    last(nod->child);
}

int main() {
    dep[1] = 1;
    null->child = null->nex = null;

    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        cin >> hp[i];
        heap[i] = null;
    }
    for (int i = 2; i <= n; ++i) {
        cin >> t1 >> op[i] >> val[i];
        nex[i] = son[t1];
        son[t1] = i;
    }
    for (int i = 1; i <= m; ++i) {
        cin >> t1 >> t2;  // 初始攻击力,初始位置
        push(heap[t2], (sakuya){ t1, i, t2 });
    }

    dfs(1);
    last(heap[1]);

    for (int i = 1; i <= n; ++i) {
        cout << guard[i] << endl;
    }
    for (int i = 1; i <= m; ++i) {
        cout << kill[i] << endl;
    }

    return 0;
}
2023/5/28 17:09
加载中...