1 条题解

  • 3
    @ 2024-11-25 16:36:26

    做法

    我们先把所有的AiA_i按照wiw_i进行排序,可以发现答案肯定是小于等于w1+nw_1 + n、大于等于w1w_1的。所以我们先设ans=w1ans=w1。接下来我们考虑剩下的Ai(i(2,n))A_i(i∈(2,n))序列如何对ansans进行更新。由题,对于某个ii,如果说fi+wians+1f_i+w_i \geq ans + 1的话,那么就可以对答案进行更新。化简得fians+1wif_i \geq ans + 1 - w_i。我们设check(x)check(x)为此时AiA_i的所有区间中mexmex小于xx的区间数。易得check(x)check(x)是非严格单调函数。所以此不等式可以转换成check(fi)check(ans+1wi)check(f_i) \geq check(ans + 1 - w_i),即kcheck(fi)check(ans+1wi)k \geq check(f_i) \geq check(ans + 1 - w_i)kcheck(ans+1wi)k \geq check(ans + 1 - w_i)。此时ansans的值循环++,直到不满足条件再枚举下一个AiA_i 接下来我们来讨论如何快速求出check(x)check(x)的值,可以使用双指针解决这个问题。对于每个右端点rr,存在左端点LL使得 mex(0L1,r)k,mex(Lr,r)<kmex(0 \to L-1,r) \leq k,mex(L \to r,r) < k,且LLrr非严格单调递增。所以我们可以使用一个桶来维护每个数在LrL \to r间出现的次数。再用一个变量cntcnt来记录ton[0,x1]ton[0,x-1]间值不等于00的个数。当cnt=midcnt=mid时代表在ALrA_{L \to r}中包含0mid10 \to mid-1中的所有数,此时左端点右移直至cnt<midcnt<mid。如图

    时间复杂度

    每次checkcheck的时间复杂度为Θ(n)Θ(n),因为answ1+nans \leq w_1 + n,所以ansans最多加nn次,内层while复杂度为Θ(n)Θ(n),外层for循环的时间复杂度也为Θ(n)Θ(n)。所以综合的时间复杂度为Θ(n(n+n))=Θ(n2)Θ(n*(n+n))=Θ(n²)

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e4 + 10;
    int n, a[N];
    int ton[N], cnt;
    struct node
    {
        int k, w, m;
        unsigned long long seed;
    } q[N];
    int k, w, m;
    bool cmp(node x, node y)
    {
        if (x.w != y.w)
            return x.w > y.w;
        return x.m > y.m;
    }
    unsigned long long _rand(unsigned long long &seed)
    {
        seed ^= seed << 13;
        seed ^= seed >> 7;
        seed ^= seed << 17;
        return seed;
    }
    inline int check(int mid)
    {
        memset(ton, 0, sizeof ton);
        int res = 0;
        cnt = 0;
        int l = 1, r = 1;
        for (; r <= n; r++)
        {
            if (ton[a[r]] == 0)
            {
                if (a[r] < mid)
                {
                    cnt++;
                    ton[a[r]]++;
                    while (l <= r && cnt == mid)
                    {
                        ton[a[l]]--;
                        if (ton[a[l]] == 0)
                            cnt--;
                        l++;
                    }
                }
            }
            else
                ton[a[r]]++;
            res += r - l + 1;
        }
        return res;
    }
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d%d%d%llu", &q[i].k, &q[i].w, &q[i].m, &q[i].seed);
        sort(q + 1, q + 1 + n, cmp);
        int ans = q[1].w;
        for (int i = 1; i <= n; i++)
        {
            k = q[i].k, w = q[i].w, m = q[i].m;
            unsigned long long se = q[i].seed;
            for (int j = 1; j <= n; j++)
            {
                a[j] = _rand(se) % q[i].m;
            }
            while (check(ans - w + 1) <= k)
                ans++;
        }
        printf("%d\n", ans);
        return 0;
    }
    
    

    信息

    ID
    154
    时间
    1500ms
    内存
    512MiB
    难度
    9
    标签
    递交数
    223
    已通过
    16
    上传者