首页 > 其他分享 >ABC337

ABC337

时间:2024-05-22 21:41:27浏览次数:27  
标签:std box 颜色 color ABC337 int ans

基本情况

ABC 秒了,D 数组在空间复杂度上面第一次疯狂吃亏,吃了两次罚时过。

赛后看官方题解,发现C做法薄纱我。

C - Lining Up 2

https://atcoder.jp/contests/abc337/tasks/abc337_c

这题一眼链表,我用双向链表实现,代码石山。

官方题解就题论题,更本质。

其实这题并没必要开双向链表,因为实际上只有一种位置关系,左到右。

直接维护一个类似单链表的数据结构就行了。

#include <iostream>
#include <vector>

int main() {
    using namespace std;
    unsigned N;
    cin >> N;

    vector<unsigned> B(N + 1, N + 1); // B[i] 存储下标对应的人的右边的人
    unsigned front;// 队头

    for(unsigned i = 1; i <= N; ++i){
        int A;
        cin >> A; 
        if(A < 0)
            front = i;//维护队头
        else
            B[A] = i; //更新A右边的人
    }

    while(front <= N){ // 就类似邻接表遍历,从队头开始
        cout << front << " ";
        front = B[front];
    }
    cout << endl;
    return 0;
}

E - Bad Juice

https://atcoder.jp/contests/abc337/tasks/abc337_e

看似是交互,实则是结合bitmask的构造题。

因为每个人是否拉肚子就 \(0,1\) 两种情况,所以可以按位构造。

对于第 \(i\) 个人,让他喝完编号第 \(i\) 为 \(1\) 的所有果汁。

如果第 \(i\) 个人中毒了,那么第 \(i\) 位为 \(1\) 的果汁肯定有问题,这里每个 \(i\) 中毒所表示的信息是不互相冲突的,可以叠加的:

如果第 \(3,4,6,7\) 个人中毒了,那么就说明有问题的果汁其 \(3,4,6,7\) 位都为 \(1\)

这样只要最多拉 \(m,(n \leq 2^m)\) 个人就能涵盖所有状况,可以证明拉的人最少。

把所有 \(i\) 中毒的位全部或上去,答案就是中毒的果汁。

signed main() {

    std::cin.tie(nullptr)->sync_with_stdio(false);

    int n;
    std::cin >> n;

    int m = 0;
    while ((1 << m) < n) {m += 1;}
    std::cout << m << std::endl;

    for (int i = 0; i < m; i++) {//选n个人品尝
        std::vector<int> res;
        for (int j = 0; j < n; j++) if (j & (1 << i)) {//如果j果汁第i位是1,就让i品尝
            res.push_back(j + 1);
        }
        std::cout << sz(res) << ' ';
        for (auto& x : res) {std::cout << x << ' ';}
        std::cout << std::endl;
    }

    std::string s;
    std::cin >> s;

    int ans = 0;

    for (int i = 0; i < m; i++) if (s[i] == '1') {
        ans |= (1 << i);//有毒的果汁第i位肯定为1
    }

    std::cout << (ans + 1) << std::endl;

    return 0;
}

F - Usual Color Ball Problems

https://atcoder.jp/contests/abc337/tasks/abc337_f

超级恶心的滑动窗口。

为了方便起见,我们考虑序列

\[C' = (C'_1, C'_2, \ldots, C'_{2N}) \coloneqq (C_1, C_2, \ldots, C_{N}, C_1, C_2, \ldots, C_{N}), \]

这个序列是通过连接两个给定序列的副本得到的,并且将此问题看作是要找到针对 \(C'\) 的段 \([l, l+N-1]\) 的操作中盒子中的球的总数,对于每个 \(l = 1, 2, \ldots, N\)。令 \(f(c, l, r)\) 表示段 \([l, r]\) 中颜色为 \(c\) 的球的数量,\(g(c)\) 表示整个原始序列 \(C\) 中颜色为 \(c\) 的球的数量。

首先,我们考虑如何找到固定段 \([l, l+N-1]\) 的答案。作为针对段 \([l, l+N-1]\) 的操作的结果,如果用于存储颜色为 \(c\) 的球的箱子数量为 \(b(c, l)\),那么结果中颜色为 \(c\) 的球的数量是 \(\min\lbrace b(c, l) \times K, g(c)\rbrace\),因此答案是

\[\mathrm{ans}_l = \sum_{c = 1}^N \min\lbrace b(c, l) \times K, g(c)\rbrace. \]

一旦我们找到每种颜色 \(c\) 的 \(b(c, l)\),我们也可以找到 \(\mathrm{ans}_l\),因此我们接下来考虑如何找到它。

如果一个球被放入一个空箱子中(这增加了用于该颜色的箱子的数量),如果这个球是要处理的颜色的第 \(1\) 个、\((K+1)\) 个、\((2K+1)\) 个、\((3K+1)\) 个等球,则会消耗一个空箱子。因此,让我们称每种颜色的第 \(1\) 个、\((K+1)\) 个、\((2K+1)\) 个、\((3K+1)\) 个等球为机会球

每次处理一个机会球(任何颜色的)时,都会消耗一个空箱子,因此 \(b(c, l)\) 等于前 \(M\) 个要处理的机会球中颜色为 \(c\) 的球的数量。因此,要处理的第 \(M\) 个机会球的位置是什么?

当从位置 \(l\) 开始操作时,段 \([l, r]\) 中颜色为 \(c\) 的机会球的数量是 \(\left\lceil f(c, l, r) / K \right\rceil\),因此段 \([l, r]\) 中的机会球(任何颜色的)的数量是

\[S(l, r) \coloneqq \sum_{c = 1}^N \left\lceil \frac{f(c, l, r)}{K} \right\rceil. \]

因此,要处理的第 \(M\) 个机会球的位置是使得 \(S(l, r) \geq M\) 的最小 \(r\)。记为 \(r_l\),则有 \(b(c, l) = \left\lceil f(c, l, r_l) / K \right\rceil\),因此所求的答案表示为

\[ \mathrm{ans}_l = \sum_{c = 1}^N \min\left\lbrace \left\lceil \frac{f(c, l, r_l)}{K} \right\rceil \times K, g(c) \right\rbrace. \tag{1} \]

(如果没有 \(r \leq l+N-1\) 满足 \(S(l, r) \geq M\),则为了方便起见,我们让 \(r_l \coloneqq l+N-1\)。)因此,为了找到 \(\mathrm{ans}_l\),只需要为固定的 \(l\) 找到 \(r_l\),并评估上述式子 (1)。然而,简单地对所有 \(l = 1, 2, \ldots, N\) 进行计算是不可能在执行时间限制内完成的。

相反,注意到根据上面的讨论,\(r_1 \leq r_2 \leq \cdots \leq r_N\)。为了按顺序评估 \(l = 1, 2, \ldots, N\) 的答案,\(r_l\) 可以以滑动窗口的方式高效地找到,而滑动窗口时,还要保持对当前段 \([l', r']\) 对应的值 (1),并且每次 \(l'\) 或 \(r'\) 增加一个时应用增量更新,以便以总共 \(O(N)\) 的时间找到 \(\mathrm{ans}_l\)。

signed main() {

    std::cin.tie(nullptr)->sync_with_stdio(false);

    int n, m, k;
    std::cin >> n >> m >> k;
    std::vector<int> c(n * 2);
    for (int i = 0; i < n; i++) {std::cin >> c[i]; --c[i]; c[i + n] = c[i];}//破环成链
    std::vector<int> all(n);//维护该颜色在1~n的出现次数
    for (int i = 0; i < n; i++) {all[c[i]] += 1;}
    std::vector<int> f(n);//即f(c, l, r),[l, r]区间内颜色为c的球的出现数量
    std::vector<int> box(n);//box[c]表示颜色为c的盒子的数量

    i64 ans = 0, totBox = 0;

    auto add = [&](int color, int x) {
        //消除没加之前的改颜色球对答案的影响
        ans -= std::min(box[color] * k, all[color]);
        totBox -= box[color];
        box[color] -= (f[color] + k - 1) / k;
        f[color] += x;//[l, r]区间该颜色球的数量+1
        //处理加之后的影响
        box[color] += (f[color] + k - 1) / k;//用的盒子是总数 / k向上取整
        totBox += box[color];//盒子数量加上去
        ans += std::min(box[color] * k, all[color]);//更新答案
    };

    for (int l = 0, r = 0; l < n; l++) {
        while (r < l + n and totBox < m) {add(c[r], 1); r++;}//如果盒子还没用完并且右端点也还没到头
        std::cout << ans << '\n';
        add(c[l], -1);//剪掉开头
    }

    return 0;
}

标签:std,box,颜色,color,ABC337,int,ans
From: https://www.cnblogs.com/kdlyh/p/18207182

相关文章

  • [题解]ABC337E Bad Juice
    ABC337EBadJuice一开始的想法如下:就是利用二分法,对于一个区间\([l,r]\),分成\([l,mid-1],[mid,r-1]\)两部分,各找两个朋友喝,右边还空出一个\(r\),如果前面两个朋友都没中毒,那说明\(r\)这瓶有毒。但仔细一想,我们发现\([1,n)\)的瓶子中任意一个我们分出的区间\([l,r]\),都用去了\(......
  • abc337解题报告
    A略B略C略D略E略G简要题意这题比F简单很多,但是两题都不难。考虑枚举\(w\)的位置,把它拎起来当根,然后考虑一个儿子\(son\)认为\(u\)在它的子树内。实际上,我们不可能把\(w\)拎起来当根,所以我们对\(son\)分两类讨论:\(son\)是\(w\)的儿子,我们求出\(v\)......
  • 【2024.1.29补题记录】abc335-abc337
    开篇碎碎念总是以开篇碎碎念开写,不加这个有点不太舒服qwq,又是一个周一,开始酣畅淋漓的学习(摸鱼)把之前欠债补一补然后看一下概率abc335总览是23号vp的,出了ABD三题,CWA了一发但是没de出来(没找到错误样例)赛后补了C和EC.LoongTracking很简单真的很简单!!!发现数据如果每次移动更新......
  • ABC337G Tree Inversion
    思路对于每个\(1\lei\len\)的\(i\)都要求答案,那我们考虑dp,去思考如何转移\(f_i\)。先不考虑全局,只考虑子树内的贡献,设\(g_u\)表示以\(u\)为根的子树内,对\(u\)来说满足条件的点对数。对于\(u\)的儿子\(v\),对\(v\)来说合法那么对\(u\)来说也一定合法。因为......
  • AT_abc337_d 的题解
    AT_abc337_d的题解题目大意给你一个\(H\timesW(H\timesW\leq2\times10^5)\)的矩阵,矩阵由o、x和.构成。存在一种操作:将一个.变成o。问在一段连续的区间内,需要进行多少次操作才可以将同一行或同一列中的连续\(k\)个数都变为o,若无法完成,输出-1。思考过程看......
  • AT_abc337_c的题解
    AT_abc337_c的题解题目大意就是给你一个数组$a=(a_1,a_2,\ldots,a_n)$,若$a_i$为$-1$,那么这个数的下标就是输出序列的开头,否侧,这个数在输出序列中排在$a_i$的下一个。思考过程从样例中不难发现:$1,2,\ldots,n$中的每一个数最多在$a$中出现一次;输出序列中的每一个......
  • ABC337 E Bad Juice 题解
    QuestionABC337EBadJuice交互题\(n\)瓶果汁中有\(1\)瓶是坏的,现在需要把这些果汁分给\(m\)个人,每个人可以喝任意瓶,然后通过\(m\)个人的回复判断哪一瓶是坏的需要输出最小的\(m\)以及坏果汁的编号Solution\(m\)返回的结果由\(01\)构成,自然而然想到二进制,考虑......
  • 「杂题乱刷」AT_abc337_e
    题目链接题目传送门(at)题目传送门(luogu)题意简述有\(n\)瓶果汁,其中有一瓶坏的,你需要使用最少的小白鼠使得这些小白鼠能找出已经变质的果汁的编号,对于每只小白鼠,你可以给他们喝任意瓶不重复的果汁,每瓶果汁可以被平均分。解题思路妙妙构造题。思路一:拿\(n\)个小白鼠,每个小......
  • ABC337 D Cheating Gomoku Narabe 题解
    QuestionABC337DCheatingGomokuNarabe给出一个\(H\timesW\)的矩阵,由o,x,.组成,一次操作为把一个.变成o,问需要最少多少次操作使得横着或竖着有连续的\(K\)个oSolution先来考虑只有一行的情况,我们定义一个长度为\(K\)的"窗口",假设需要把这个"窗口"里面的所有......
  • ABC337
    T1:Scoreboard模拟代码实现n=int(input())st,sa=0,0foriinrange(n):x,y=map(int,input().split())st+=x;sa+=yifst<sa:print('Aoki')ifst==sa:print('Draw')ifst>sa:print('......