zoukankan      html  css  js  c++  java
  • Codeforces Round #543 (Div. 2, based on Technocup 2019 Final Round) D. Diana and Liana

    题目链接

    Description

    一段长度为(m)的序列(a),按顺序分为(n)块,每块大小为(k)
    可以删除一些数,要求删除后 (mgeq n*k)
    再给定一个长度为(s)的序列(b),问是否能通过删除一些数(或不删),
    使得至少一块中每个数出现的次数都不小于(b)中出现的次数。

    Solution

    哈又是一道用劣法过掉的题目。

    首先只需要有一块满足条件即可。
    假设以(i)为某一块的开头,那么需要删除((i-1))%(k)个数(因为按顺序分块),
    所有(i)最远能取到的数(Next[i])就是(i+k-1+n*k-m-((i-1))%(k))
    也就是说我们可以从((i,Next[i]))中任选(k)个数组成一块。

    那么将((i,Next[i]))当作一个询问,莫队搞一搞就好啦。
    时间复杂度(O(msqrt{m}))

    Code

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    #define N 500000
    
    #define fo(i, x, y) for(int i = x; i <= y; i ++)
    #define F(x) ((x + 1) / sq)
    
    void read(int &x) {
        char ch = getchar(); x = 0;
        while (ch < '0' || ch > '9') ch = getchar();
        while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + ch - 48, ch = getchar();
    }
    
    struct Ques { int l, r; } q[N + 1];
    
    int a[N + 1], b[N + 1], d[N + 1], h[N + 1];
    
    int n, m, k, s, cnt = 0, tot = 0, sq;
    
    bool Cmp(Ques a, Ques b) { return F(a.l) < F(b.l) || (F(a.l) == F(b.l) && ((F(a.l) & 1) ? a.r < b.r : a.r > b.r)); }
    
    void Add(int u) { if (++ h[a[u]] == d[a[u]]) -- cnt; }
    
    void Del(int u) { if (h[a[u]] == d[a[u]]) ++ cnt; -- h[a[u]]; }
    
    int main() {
         freopen("diana.in", "r", stdin);
         freopen("diana.out", "w", stdout);
    
        read(m), read(k), read(n), read(s);
        fo(i, 1, m) read(a[i]);
        fo(i, 1, s) read(b[i]);
    
        fo(i, 1, s) if (++ d[b[i]] == 1) ++ cnt;
        fo(i, 1, m - k + 1) if (m - n * k - (i - 1) % k >= 0)
            q[ ++ tot ] = (Ques) { i, i + k - 1 + m - n * k - (i - 1) % k };
        sq = sqrt(tot);
        sort(q + 1, q + 1 + tot, Cmp);
    
        for(int l = 1, r = 0, i = 1; i <= tot; i ++) {
            while (r < q[i].r) Add(++ r);
            while (l > q[i].l) Add(-- l);
            while (r > q[i].r) Del(r --);
            while (l < q[i].l) Del(l ++);
            if (! cnt) {
                printf("%d
    ", m - n * k);
                fo(j, 1, (q[i].l - 1) % k) printf("%d ", j);
                int sum = 0;
                fo(j, q[i].l, q[i].r)
                    if (h[a[j]] > d[a[j]] && ++ sum <= m - n * k - (q[i].l - 1) % k)
                        printf("%d ", j), -- h[a[j]];
                return 0;
            }
        }
        puts("-1");
    
        return 0;
    }
    
    
  • 相关阅读:
    MyKTV项目总结
    TCP滑动窗口Sliding Window
    TCP时间戳选项Timestamp
    TCP窗口扩大选项Window Scale
    TCP最大报文段长度MSS
    TCP路径MTU发现
    TCP主动打开 之 第一次握手-发送SYN
    TCP层accept系统调用的实现分析
    Linux TCP套接字选项 之 SO_REUSEADDR && SO_REUSEPORT
    TCP层bind系统调用的实现分析
  • 原文地址:https://www.cnblogs.com/zhouzj2004/p/13777874.html
Copyright © 2011-2022 走看看