[JSOI2011]任务调度 题解

[JSOI2011]任务调度 题解

题目地址:BZOJ:Problem 5179. — [Jsoi2011]任务调度

题目描述

一台超级计算机共有N颗CPU。现在这台超级计算机有M个任务要做,但同时还要考虑到不能让CPU过热。所幸的是这台超级计算机已经将任务安排好了,现在要做的只是请你根据安排好的指令来模拟它的工作过程。一开始,这N颗CPU都没有被分配任何的任务。之后,会给你以下几类指令(CPU的编号为1到N的整数,任务的编号为1到M的整数)
指令格式 作用
ADD n k w 将 k 号任务(权值为 w)分配给 n 号 CPU
DEC n k w 将 k 号任务的权值减少 w(已知 k 号任务被分配给了 n 号 CPU)
TRANS n1 n2 将分配给 n1 号 CPU 的任务全部转移给 n2 号 CPU
MIN n 输出分配给 n 号 CPU 的任务中权值最小的任务的权值
WORK n w 将分配给 n 号 CPU 的任务中权值最小的任务的权值加上 w,如果权值最小的任务不唯一,则不更改权值,并输出一行“ ERROR”

输入输出格式

输入格式:
包含N+1行。
第1行包含三个正整数N、M、K,分别表示CPU的数目、任务数和指令数。
第2行到K+1行,每行包含一条指令。
N≤500, M≤300000, K≤300000。
保证任务的权值在 32 位有符号整型的范围内。
保证一个任务只会被分配一次(即至多被 ADD 一次)。
保证 ADD 指令、DEC 指令和 WORK 指令中的 w 是非负整数。
保证 TRANS 指令的两个参数不相同。

输出格式:
若干行,其中包括MIN语句的输出和“ERROR”输出,每个输出占一行

输入输出样例

输入样例#1:

2 3 13
ADD 1 2 100
ADD 1 1 90
MIN 1
WORK 1 20
TRANS 1 2
MIN 2
ADD 1 3 105
TRANS 2 1
MIN 1
DEC 1 3 200
MIN 1
DEC 1 1 205
WORK 1 15

输出样例#1:

90
100
100
-95
ERROR

题解

考虑左偏树来做这个题。ADD即新建节点并且合并到该CPU堆。DEC即先删点,改完权值以后再并回去。TRANS即合并两个堆。MIN即询问堆中最小值。WORK同DEC。

代码

// Code by KSkun, 2018/4
#include <cstdio>
#include <cctype>

#include <algorithm>

typedef long long LL;

inline char fgc() {
    static char buf[100000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF 
        : *p1++;
}

inline LL readint() {
    register LL res = 0, neg = 1;
    char c = fgc();
    while(c < '0' || c > '9') {
        if(c == '-') neg = -1;
        c = fgc();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = fgc();
    }
    return res * neg;
}

inline char readop() {
    char c;
    while(!isalpha(c = fgc()));
    return c;
}

const int MAXN = 300005;

struct Node {
    int fa, val, dis, ch[2];
} tr[MAXN];

inline int merge(int u, int v) {
    if(!u || !v) return u + v;
    if(tr[u].val > tr[v].val) std::swap(u, v);
    tr[u].ch[1] = merge(tr[u].ch[1], v);
    tr[tr[u].ch[1]].fa = u;
    if(tr[tr[u].ch[0]].dis < tr[tr[u].ch[1]].dis) std::swap(tr[u].ch[0], tr[u].ch[1]);
    tr[u].dis = tr[tr[u].ch[1]].dis + 1;
    return u;
}

inline bool isleft(int p) {
    return tr[tr[p].fa].ch[0] == p;
}

inline void erase(int p) {
    tr[tr[p].ch[0]].fa = tr[tr[p].ch[1]].fa = 0;
    int q = merge(tr[p].ch[0], tr[p].ch[1]);
    if(q) tr[q].fa = tr[p].fa; if(tr[p].fa) tr[tr[p].fa].ch[!isleft(p)] = q;
    for(int i = tr[p].fa; i; i = tr[i].fa) {
        if(tr[tr[i].ch[0]].dis < tr[tr[i].ch[1]].dis) std::swap(tr[i].ch[0], tr[i].ch[1]);
        if(tr[i].dis == tr[tr[i].ch[1]].dis + 1) break;
        tr[i].dis = tr[tr[i].ch[1]].dis + 1;
    }
    tr[p].fa = tr[p].ch[0] = tr[p].ch[1] = tr[p].dis = 0;
}

inline int poprt(int p) {
    tr[tr[p].ch[0]].fa = tr[tr[p].ch[1]].fa = 0;
    int q = merge(tr[p].ch[0], tr[p].ch[1]);
    tr[p].fa = tr[p].ch[0] = tr[p].ch[1] = tr[p].dis = 0;
    return q;
}

int n, m, k, x, y, z, rt[MAXN];
char op;

int main() {
    tr[0].dis = -1;
    n = readint(); m = readint(); k = readint();
    while(k--) {
        op = readop();
        if(op == 'A') {
            x = readint(); y = readint(); z = readint();
            tr[y].val = z;
            rt[x] = merge(y, rt[x]);
        } else if(op == 'D') {
            x = readint(); y = readint(); z = readint();
            if(!tr[y].fa) rt[x] = poprt(y);
            else erase(y);
            tr[y].val -= z;
            rt[x] = merge(rt[x], y);
        } else if(op == 'T') {
            x = readint(); y = readint();
            rt[y] = merge(rt[x], rt[y]);
            rt[x] = 0;
        } else if(op == 'M') {
            x = readint();
            printf("%d\n", tr[rt[x]].val);
        } else {
            x = readint(); y = readint(); int p = rt[x];
            if((tr[p].ch[0] && tr[tr[p].ch[0]].val == tr[p].val)
                || (tr[p].ch[1] && tr[tr[p].ch[1]].val == tr[p].val)) {
                puts("ERROR");
                continue;
            }
            rt[x] = poprt(p);
            tr[p].val += y;
            rt[x] = merge(rt[x], p);
        }
    }
    return 0;
}


发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据