P2564:「SCOI2009」生日礼物题解

解法

假的单调队列哦。

考虑将每个类别元素的下标记好,然后先把每个类别标号最小的放入 multiset,然后对答案进行更新:每次取出最大和最小值做差更新,然后把最小值的下标更新后重新扔进 multiset 中。如果 multiset 中所有的类别都已经枚举完毕,那么直接跳出循环进行输出即可。

代码

// P2564.cpp
#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct node
{
    ll typ, val, dep;
    bool operator<(const node &nd) const { return val < nd.val; }
};
int n, k;
vector<int> typs[100];
multiset<node> st;

int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= k; i++)
    {
        int ti;
        scanf("%d", &ti);
        while (ti--)
        {
            int num;
            scanf("%d", &num), typs[i].push_back(num);
        }
        st.insert(node{i, typs[i][0], 0});
    }
    ll ans = 0x3f3f3f3f3f3f3f3f;
    int full = 0;
    while (full < k)
    {
        node small = *st.begin(), biggest = *(--st.end());
        ans = min(ans, biggest.val - small.val);
        st.erase(st.begin());
        if (small.dep + 1 < typs[small.typ].size())
            small.val = typs[small.typ][small.dep + 1], small.dep++;
        else
            full++;
        st.insert(small);
    }
    node small = *st.begin(), biggest = *(--st.end());
    ans = min(ans, biggest.val - small.val);
    printf("%lld", ans);
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *