首页 > 其他分享 >Sleeping Cup #1 Editorials

Sleeping Cup #1 Editorials

时间:2024-07-16 21:52:11浏览次数:7  
标签:体力 Editorials 小猪 Cup int dfrac move Sleeping log

A - Sleeping pairs

  • 很明显,能删的要立刻删,它们会阻碍交换。
  • 一共要删除 \(n\) 列,这需要 \(n\) 点体力。
  • 由于删除时总要保证两列字符一致,故两列 X 的个数要相等。设两列 X 的个数原来相差 \(b\) 个,则交换一行 XZ(或 ZX)会使得某一列减少一个 X,而另一列增加一个 X,差值减少 \(2\),故这需要 \(\dfrac{b}{2}\)​ 点体力。
  • 由样例 \(1\) 可知,删除两行相邻的 XZZX 需要 \(1\) 点额外体力(删除所需的体力已经计算过了)。上一步完成后,ZXXZ 一定都存在(否则两列 X 的个数不可能相同),因此总会有两行相邻的 XZZX。设上一步结束后还剩下 \(c\) 列,则这需要 \(\dfrac{c}{2}\)​ 点体力。
#include <bits/stdc++.h>

using namespace std;

int n;
int a, b, c;

string s;

int main()
{
    freopen("pairs.in", "r", stdin);
    freopen("pairs.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        cin >> s;
        if (s == "XZ")
        {
            b++;
            c++;
        }
        if (s == "ZX")
        {
            b--;
            c++;
        }
    }
    a = n + abs(b) / 2 + c / 2;
    printf("%d", a);
    return 0;
}

B - Have a check

模拟即可。样例已经涵盖了所有注意事项。

#include <bits/stdc++.h>

using namespace std;

string check(string answer, string output)
{
    if (answer == output)
    {
        return "Accepted.";
    }
    int line = 1, column = 1, al = answer.size(), ol = output.size();
    stringstream conv;
    string res;
    conv << "Wrong Answer: ";
    for (int i = 0; i < min(al, ol); i++)
    {
        if (answer[i] != output[i])
        {
            if (answer[i] == '\n')
            {
                conv << "Extra Character";
            }
            else if (output[i] == '\n')
            {
                conv << "Missing Character";
            }
            else
            {
                conv << "Wrong Answer";
            }
            conv << " on Line " << line << ", Column " << column << ".";
            getline(conv, res);
            return res;
        }
        if (answer[i] == '\n')
        {
            line++;
            column = 1;
        }
        else
        {
            column++;
        }
    }
    if (al > ol)
    {
        if (answer[ol] == '\n')
        {
            conv << "Missing Line on Line " << line + 1 << ".";
        }
        else
        {
            conv << "Missing Character on Line " << line << ", Column " << column << ".";
        }
    }
    else
    {
        if (output[al] == '\n')
        {
            conv << "Extra Line on Line " << line + 1 << ".";
        }
        else
        {
            conv << "Extra Character on Line " << line << ", Column " << column << ".";
        }
    }
    getline(conv, res);
    return res;
}

int main()
{
    freopen("check.in", "r", stdin);
    freopen("check.out", "w", stdout);
    string ansa, out;
    stringstream s0, s1, s2;
    bool sepa = false;
    char c = getchar();
    while (c != EOF)
    {
        s0 << (int)c << endl;
        if (c == 127)
        {
            sepa = true;
        }
        else if (sepa)
        {
            s2 << '*';
        }
        else
        {
            s1 << '*';
        }
        c = getchar();
    }
    s1 >> ansa;
    s2 >> out;
    int tmp = 0, cnt = 0;
    sepa = false;
    while (s0 >> tmp)
    {
        if (tmp == 127)
        {
            sepa = true;
            cnt = 0;
        }
        else
        {
            if (sepa)
            {
                out[cnt] = tmp;
            }
            else
            {
                ansa[cnt] = tmp;
            }
            cnt++;
        }
    }
    cout << check(ansa, out);
    return 0;
}

C - Moving like a spider

  • 由于向上运动不花费体力,会合点的 \(y\) 坐标可以无限大,因此只需要考虑会合点的 \(x\) 坐标即可。
  • 不难发现,每只蜘蛛最优移动路径只有两种:
    • 在当前 \(y\) 坐标上改变 \(x\) 坐标(设改变量为 \(\Delta x\)),然后向上运动,花费 \(ry_0\Delta x\) 点体力(其中 \(y_0\) 是初始的 \(y\) 坐标)。
    • 向下运动到中心点 \(O\),然后向上运动,花费 \(dy_0\) 点体力。
  • 由上可知,我们只需要关注 \(\Delta x\) 和 \(l=\dfrac{d}{r}\) 的大小关系,即可确定每只蜘蛛的最优移动路径。
  • 因此,我们枚举会合点的 \(x\) 坐标,然后差分(结合斜率)维护花费的总体力即可。
#include <bits/stdc++.h>

#define int long long

using namespace std;

const int N = 1e5 + 12;

int K[N], D[N], R[N], A[N];

int move(int f, int s, int n)
{
    return (f + s + n) % n;
}

int dis(int f, int t, int n)
{
    int ans = abs(t - f);
    return min(ans, n - ans);
}

void build(int n, int d, int r, int l)
{
    for (int i = 0; i <= n - 1; i++)
    {
        if (l >= n / 2 && n % 2 == 1)
        {
            // i = 1, n = 7
            // pos: 0 1 2 3 4 5 6
            // dis: 1 0 1 2 3 3 2
            K[move(i, n / 2 + 1, n)] += -1 * A[i];
            K[move(i, n / 2 + 2, n)] += -1 * A[i];
            K[move(i, 1, n)] += 2 * A[i];
        }

        if (l >= n / 2 && n % 2 == 0)
        {
            // i = 1, n = 6
            // pos: 0 1 2 3 4 5
            // dis: 1 0 1 2 3 2
            K[move(i, n / 2 + 1, n)] += -2 * A[i];
            K[move(i, 1, n)] += 2 * A[i];
        }
        if (l < n / 2)
        {
            // i = 1, n = 8, l = 2
            // pos: 0 1 2 3 4 5 6 7
            // dis: 1 0 1 2 d d d 2
            R[move(i, l + 1, n)] += -l * A[i];
            K[move(i, l + 1, n)] += -1 * A[i];
            D[move(i, l + 1, n)] += 1 * A[i];
            R[move(i, -l, n)] += l * A[i] + A[i];
            K[move(i, -l, n)] += -1 * A[i];
            D[move(i, -l, n)] += -1 * A[i];
            K[move(i, 1, n)] += 2 * A[i];
        }
    }
    return;
}

signed main()
{
    freopen("spider.in", "r", stdin);
    freopen("spider.out", "w", stdout);
    int m, n, d, r;
    cin >> m >> n >> d >> r;
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        A[x] += y;
    }
    int l = d / r;
    long long a0 = 0, d0 = 0, r0 = 0;
    for (int i = 0; i <= n - 1; i++)
    {
        if (dis(0, i, n) <= l)
        {
            a0 += dis(0, i, n) * r * A[i];
            r0 += dis(0, i, n) * A[i];
        }
        else
        {
            a0 += d * A[i];
            d0 += A[i];
        }
    }
    long long a1 = 0, d1 = 0, r1 = 0;
    for (int i = 0; i <= n - 1; i++)
    {
        if (dis(1, i, n) <= l)
        {
            a1 += dis(1, i, n) * r * A[i];
            r1 += dis(1, i, n) * A[i];
        }
        else
        {
            a1 += d * A[i];
            d1 += A[i];
        }
    }
    build(n, d, r, l);
    long long kk = r1 - r0 - R[1], dd = d1, rr = r1, aa = a1, ans = min(a0, a1);
    for (int i = 2; i <= n - 1; i++)
    {
        kk += K[i], dd += D[i], rr += R[i];
        rr += kk;
        aa = rr * r + dd * d;
        ans = min(ans, aa);
    }
    cout << ans << endl;
    return 0;
}

D - Faster than expected

第一部分

上述代码的最坏时间复杂度是 \(O(nT \log n)\)。

第二部分

为了证明中间的小猪不会出现左右往复移动而使时间复杂度达到 \(O(n^2T)\) 的情况,我们考虑把场上所有的小猪从左向右平分成三分,分别记为 \(A,B,C\)。

根据题意,在 \(A,B,C\) 中都至少有一只小猪还没下桥的情况下,\(A\) 中的小猪总会向左移动,而 \(C\) 中的小猪总会向左移动。\(\dfrac{T}{2}\) 秒后,\(A\) 中任意一只小猪和 \(C\) 中任意一只小猪之间的距离将不小于 \(T\),因此它们之间一定有一组全部下桥了。

由上可知,时间每过去 \(\dfrac{T}{2}\) 秒,桥上小猪的数量都将至少减少 \(\dfrac{1}{3}\),即剩下原来的 \(\dfrac{2}{3}\) 或更少。因此,整个过程最多持续 \(\dfrac{T}{2} \cdot \log _{\frac{3}{2}} n=O(T \log n)\) 秒。

阅读程序可知,它 while 循环内程序的时间复杂度为 \(O(n)\),而 while 循环每执行一次相当于时间流逝一秒,因此 while 循环最多会执行 \(O(T \log n)\) 次。

综上,上述代码的时间复杂度不高于 \(O(nT \log n)\)。

第三部分

只要让 \(T\) 远大于 \(n\)(此时可以忽略 \(n\) 对小猪位置的影响),且 \(T,n\) 足够大,将 \(n\) 只小猪都放在 \(\dfrac{T}{3}\) 位置(时间每过去 \(\dfrac{T}{3}\) 秒,桥上小猪的数量都将减少 \(\dfrac{1}{2}\)),即可使上述代码的时间复杂度退化到 \(O(nT \log n)\)。

例如:

  • \(n=10^6\)。
  • \(T=3 \times 10^{18}\)。
  • \(a_i=10^{18}+i\)。

标签:体力,Editorials,小猪,Cup,int,dfrac,move,Sleeping,log
From: https://www.cnblogs.com/cq-irritater/p/18306204/Sleeping-Cup-1-sol

相关文章

  • 介绍自动驾驶的感知任务--3D Occupancy Semantic Prediction
    介绍自动驾驶感知任务中的--3DOccupancySemanticPrediction什么是Occupancy自动驾驶领域,按照传统会分为perception,prediction,planning和control四大部分,有时会加上map。其中最为重要的就是perception,也是目前自动驾驶的瓶颈所在,如果感知算法给了下游任务错误的视觉信息,......
  • The 1st Universal Cup. Stage 15: Hangzhou
    Preface久违的线下训练,结果因为祁神有急事赶回家了就我和徐神两个人打开场就感觉有点不对劲怎么没有签到,然后全程对着几个题红温还想了一堆假算法,最后愉悦暴毙感觉这场题本身质量都挺高的,但最后只写了5个(赛后补了一个),等以后有时间再来补补吧A.TurnontheLight徐神开场一......
  • "No Directionality widget found." 在使用cupertino的时候出现了这个问题
    在使用cupertino的时候出现了这个问题,不过使用其他组件库也是类似的原代码:import'package:flutter/cupertino.dart';voidmain()=>runApp(constCupertinoTestRoute());classCupertinoTestRouteextendsStatelessWidget{constCupertinoTestRoute({Key?key}):s......
  • 如何参与 Sleeping Cup 的筹备工作?
    SleepingCup公开赛的筹备工作中需要以下各方参与:出题人(单人或团体)提供原创题目idea。出题人的最低资质要求暂时为5级勾及以上。在出题人中,需有一名负责人。请注意,负责人必须全程切实对整场比赛负责、对每道赛题负责,而不能仅仅只是挂名。审核员将主要与负责人进行对接和......
  • 2.2 实验三、自动生成语法分析程序(JavaCUP)
    help-assignment2.3实验三、自动生成语法分析程序(JavaCUP)实验三要求你下载一个语法分析程序自动生成工具JavaCUP,利用该工具自动产生一个Oberon-0语言的语法分析和语法制导翻译程序;生成的程序源代码是以Java语言编写的。2.3.1实验步骤3.1、下载自动生成工具Java......
  • 2024年城市规划、建设与区域发展国际学术会议(ICUPCRD 2024)
    2024年城市规划、建设与区域发展国际学术会议(ICUPCRD2024)2024InternationalConferenceonUrbanPlanning,ConstructionandRegionalDevelopment会议地点:上海,中国网址:www.icupcrd.com邮箱:[email protected]投稿主题请注明:ICUPCRD2024+通讯作者姓名(否则无法......
  • 密码管理工具Buttercup
     如果你在寻找一款优先考虑本地使用的密码管理器,那么Buttercup 就是一个针对macOS、Linux和Windows的理想选择。如果你不需要云同步功能,但希望寻找一款与KeePass用户体验不同的密码管理器,那么Buttercup将是一个好的替代品。这是一个带有简洁用户界面的跨平台开源密......
  • codeforces 1442 D Codeforces Round 681 (Div. 1, based on VK Cup 2019-2020 - Fina
    链接大意就是给你n组物品,这n组物品里面每组有\(t_i\)个,且他们是按照价值不降的顺序排列的。现在允许取k个物品,每个物品必须取在数组的开头处,每个物品在被取用后就会消失。问你最大能够拿到多少价值的物品。其中\(n,k\leq1500,\sumt_i\leq1e6,a_i\leq1e8\)很背包吧。可......
  • 第二十二届SCU程序设计竞赛(Tencent CUP)
    ProblemA.配对质数此题事先把素数筛出来,由于从前往后可能会导致后面的数字无法配对,我们只需从后往前,把数x/2得到的两个数,即可完成配对操作#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;template<typenameT>inlinevoidread(T&x)......
  • [Paper Reading] FlashOcc: Fast and Memory-Efficient Occupancy Prediction via Cha
    FlashOcc:FastandMemory-EfficientOccupancyPredictionviaChannel-to-HeightPluginlink时间:23.11机构:houmo.ai后摩智能TL;DR当时比较流行的OCC方案内存与计算复杂度较高,本文提出一种称为FlashOcc的方法,仅使用2D卷积将特征由二维空间lift到3D空间。MethodImageEn......