其他分享
首页 > 其他分享> > 「Code+#2」火锅盛宴

「Code+#2」火锅盛宴

作者:互联网

博主的 BiBi 时间

话说因为这道题当天下午去吃了火锅,结果一身味。。。

明明只打了 \(8pts\) 却意外收获 \(15pts\)!

竟然会用 \(set\) 了 \(QwQ\)。

Code

#include <set>
#include <cstdio>
#include <iostream>
using namespace std;

const int N = 1e5 + 5, Q = 5e5 + 5;

int n, q, a[N], tot[N], sum[N << 2];
set <int> s;
set <int> :: iterator it;

int read() {
    int x = 0, f = 1; char s;
    while((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
    while(s >= '0' && s <= '9') {x = (x << 1) + (x << 3) + (s ^ 48); s = getchar();}
    return x * f;
}

int query(const int o, const int l, const int r, const int L, const int R) {
    if(l > R || r < L) return 0;
    if(l >= L && r <= R) return sum[o];
    int mid = l + r >> 1;
    return query(o << 1, l, mid, L, R) + query(o << 1 | 1, mid + 1, r, L, R);
}

void pushUp(const int o) {
    if(! o) return;
    sum[o] = sum[o << 1] + sum[o << 1 | 1];
    return;
}

void update(const int o, const int l, const int r, const int p, const int k) {
    if(l > p || r < p) return;
    if(l == r) {
        sum[o] += k;
        return;
    }
    int mid = l + r >> 1;
    update(o << 1, l, mid, p, k); update(o << 1 | 1, mid + 1, r, p, k);
    pushUp(o);
}

int main() {
    int op, x, y;
    for(int T = read(); T; -- T) {
        n = read(); s.clear();
        for(int i = 1; i <= n; ++ i) a[i] = read(), tot[i] = 0;
        for(int i = 1; i <= (n << 2); ++ i) sum[i] = 0;
        q = read();
        while(q --) {
            x = read(); op = read();
            if(op == 0) {
                x = read();
                if(! tot[x]) s.insert(x);
                update(1, 1, n, x, 1); ++ tot[x];
            }
            else if(op == 1) {
                if(s.empty()) puts("Yazid is angry.");
                else {
                    it = s.begin();
                    printf("%d\n", *it);
                    -- tot[*it];
                    update(1, 1, n, *it, -1);
                    if(tot[*it] == 0) s.erase(*it);
                }
            }
            else if(op == 2) {
                x = read();
                if(tot[x]) {
                    puts("Succeeded!");
                    update(1, 1, n, x, -1);
                    -- tot[x];
                    if(tot[x] == 0) s.erase(x);
                }
                else puts("YJQQQAQ is angry.");
            }
            else {
                x = read(), y = read();
                printf("%d\n", query(1, 1, n, x, y));
            }
        }
    }
    return 0;
}

Solution

其实这道题的方法有很多,比如我旁边的那位用了线段树+优先队列,某谷上只有 \(30pts\),不过在 \(usOJ\) 上能过就行了。

我是用的 树状数组+模拟链表。(太棒了学到许多)

用链表来维护每种食物下锅情况。定义 \(head[i]\) 为第 \(i\) 种食物的表头,\(tail[i]\) 为表尾。\(nxt\) 数组用来表示连接关系。

用树状数组来维护每种食物可以出锅的个数。

另外这里的 \(upper\) 是树状数组中第一个大于某个值的的下标。(另外这里不会证明,有什么大佬可以证一下吗)

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 1e5 + 5, Q = 5e5 + 5;

int n, q, s[N], t[Q], op[Q], a[Q], b[Q], id[Q], cnt, head[N], nxt[Q], tail[N], data[Q], tot;
struct BIT {
    int sum[N];

    void clear() {memset(sum, 0, sizeof sum);}

    int lowbit(const int x) {return x & -x;}

    void update(int x, const int k) {
        while(x <= n) sum[x] += k, x += lowbit(x);
    }

    int query(int x) {
        int r = 0;
        while(x) r += sum[x], x -= lowbit(x);
        return r;
    }

    int upper(const int lim) {
        int x = 0, r = 0;
        for(int i = (1 << 16); i; i >>= 1)
            if(x + i <= n && r + sum[x + i] <= lim) r += sum[x += i];
        return x + 1;
    }
} bit;

int read() {
    int x = 0, f = 1; char s;
    while((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
    while(s >= '0' && s <= '9') {x = (x << 1) + (x << 3) + (s ^ 48); s = getchar();}
    return x * f;
}

bool cmp(const int x, const int y) {return t[x] + s[a[x]] < t[y] + s[a[y]];}

void add(const int x, const int k) {
    if(! head[x]) head[x] = tail[x] = ++ tot;
    else nxt[tail[x]] = ++ tot, tail[x] = tot;
    data[tot] = k;
}

void Insert(const int x) {
    bit.update(x, 1);
    head[x] = nxt[head[x]];
    if(! head[x]) tail[x] = 0;
}

int main() {
    for(int T = read(); T; -- T) {
        cnt = tot = 0;
        memset(head, 0, sizeof head);
        memset(tail, 0, sizeof tail);
        memset(nxt, 0, sizeof nxt);
        n = read(); bit.clear();
        for(int i = 1; i <= n; ++ i) s[i] = read();
        q = read();
        for(int i = 1; i <= q; ++ i) {
            t[i] = read(), op[i] = read();
            if(op[i] == 0) a[i] = read(), id[++ cnt] = i;
            else if(op[i] == 2) a[i] = read();
            else if(op[i] == 3) a[i] = read(), b[i] = read();
        }
        sort(id + 1, id + cnt + 1, cmp);
        int p = 1;
        for(int i = 1; i <= q; ++ i) {
            while(p <= cnt && t[id[p]] + s[a[id[p]]] <= t[i]) Insert(a[id[p]]), ++ p;
            if(op[i] == 0) add(a[i], t[i] + s[a[i]]);
            else if(op[i] == 1) {
                int tmp = bit.upper(0);
                if(tmp == n + 1) puts("Yazid is angry.");
                else printf("%d\n", tmp), bit.update(tmp, -1);
            }
            else if(op[i] == 2) {
                if(bit.query(a[i]) - bit.query(a[i] - 1)) puts("Succeeded!"), bit.update(a[i], -1);
                else if(head[a[i]]) printf("%d\n", data[head[a[i]]] - t[i]);
                else puts("YJQQQAQ is angry.");
            }
            else printf("%d\n", bit.query(b[i]) - bit.query(a[i] - 1));
        }
    }
    return 0;
}

标签:+#,Code,return,火锅,int,sum,while,const,include
来源: https://www.cnblogs.com/AWhiteWall/p/13025603.html