10 月 11 日模拟赛总结

Before

本文章在洛谷博客同步发布

Contest-Link

预期 100+100+0+0=200

实际 100+80+0+0=180

挂分 20

rk4/totrk8。行。

首先扫了遍四题,T1 一眼丁真鉴定为神秘数学题,然后瞪了 30min 没瞪出来,跳 T2;T2 一眼丁真鉴定推式子,举了几个加法例子发现 ab=(a+b1)mod(k1)+1,有 ab=(a×b1)mod(k1)+1,然后就做完了。

然后看第三题,鉴定为神秘树形 DP,然后发现一个点可以分裂,不能模拟,不会,寄。打了个 puts("Alice") 跑路。

第四题看了一眼,鉴定为规律题,鉴定为周期性,但是好像周期次数没啥规律,寄。

然后开始摆摆摆摆摆摆摆摆摆摆摆摆摆,摆摆摆摆摆摆摆。摆得人都没了。

赛后发现 T2 k12,我看成了 k10,寄。

T1

Description

给定一条水平直线和两个点,求经过水平线的两点的最短距离。

输入一行五个整数 k,x1,y1,x2,y2

一行一个自然数,表示平方后的答案。

0|k|,|x1|,|y1|,|x2|,|y2|5×108

Solution

经典将军饮马,不会的看这里

考场想法:将军饮马。

考场寄因:没寄。

时间复杂度 O(1),空间复杂度 O(1)

Code

100pts:

// 2023/10/9 PikachuQAQ

#include <iostream>
#include <cmath>

using namespace std;

typedef long long ll;

ll k, xa, ya, xb, yb;

ll dist(ll xa, ll ya, ll xb, ll yb) {
    return (xa - xb) * (xa - xb) + (ya - yb) * (ya - yb);
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> k >> xa >> ya >> xb >> yb;
    if (ya >= k && yb <= k || ya <= k && yb >= k) {
        cout << dist(xa, ya, xb, yb) << '\n';
    } else {
        cout << dist(xa, 2 * k - ya, xb, yb) << '\n';
    }

    return 0;
}

T2

Description

数轴上有一些靶子,对应一些不交的区间,每个靶子有个红心区间,按顺序进行射击,根据重靶、丢靶、红心、非红心输出对应的消息。

第一行三个自然数 n,m,k,含义如题面所述。 接下来 n 行,每行四个自然数 li,xi,yi,ri,描述了靶子的信息。 接下来一行 k 个自然数,表示每次射击的坐标。

对于每个询问,输出一行一个对应的结果。

1n,k105,1lixiyirim109

Solution

因为区间无交集,所以我们可以直接二分,一个靶子一定会有四个坐标,对于一个坐标我们分类讨论即可。

考场想法:二分。

考场寄因:没寄。

时间复杂度 O(klogn),空间复杂度 O(nlogn)

Code

100pts:

// 2023/10/9 PikachuQAQ

#include <iostream>
#include <algorithm>
#include <map>

using namespace std;

typedef long long ll;

const int kMaxN = 4e5 + 7, kMaxM = kMaxN << 2;

int n, m, k, a[kMaxN], len;
bool vis[kMaxN];
map<int, int> mp;

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> m >> k;
    for (int i = 1, l, x, y, r; i <= n; i++) {
        cin >> l >> x >> y >> r;
        a[++len] = l, a[++len] = r, a[++len] = x, a[++len] = y;
        mp[l] = mp[r] = 1, mp[x] = mp[y] = 2;
    }
    sort(a + 1, a + len + 1);
    for (int i = 1, x; i <= k; i++) {
        cin >> x;
        ll p = lower_bound(a + 1, a + len + 1, x) - a, g = p % 4, q = (p - 1) / 4 + 1;
        if (g == 1 && mp[x] == 0) {
            cout << "Failed\n";
        } else if (vis[q]) {
            cout << "Again\n";
        } else if (g == 1 && mp[x] == 1 || g == 2 && mp[x] != 2 || g == 0) {
            cout << "Normal\n";
            vis[q] = 1;
        } else {
            cout << "Perfect\n";
            vis[q] = 1;
        }
    }

    return 0;
}

T3

Description

给定一个序列,求子段和绝对值的最大值。

第一行两个自然数 n,m。 接下来一行 n 个整数,表示序列的初始值。 接下来 m 行,每行两个自然数,描述了一个查询。

对于每个询问,输出一行一个自然数,表示答案。

1n2×105,1m3×106,0|ai|109

Solution

显然线段树是可以的,但是好像卡不过去,只能拿 70 分。普通线段树的做法是 O(mlogn+n) 的。

所以我们可以用一种特殊的线段树——猫树维护,其仅支持 O(1) 查询,不能修改,建树复杂度 O(nlogn)

然后就达到了 O(nlogn+m) 的时间复杂度。

但是我赛后没写出来,但我们还有一种数据结构:ST 表。其实现后时间复杂度为 O(nlogn+m)

考场想法:暴力。

考场寄因:没寄。

时间复杂度 O(nlogn+m),空间复杂度 O(nlogn)

Code

100pts:

// 2023/10/9 PikachuQAQ

#include <iostream>
#include <cmath>

using namespace std;

typedef long long ll;

const ll kMaxN = 2e5 + 7, LgMax = 28, INF = 4e18;

ll n, q, a[kMaxN], pre[kMaxN], minn[kMaxN][LgMax], maxn[kMaxN][LgMax], lg[kMaxN];

ll QueryMin(ll l, ll r) {
    if (l > r) {
        return INF;
    } else if (l == 0) {
        return min(QueryMin(l + 1, r), 0ll);
    } else {
        int k = lg[r - l + 1];
        return min(minn[l][k], minn[r - (1 << k) + 1][k]);
    }
}

ll QueryMax(ll l, ll r) {
    if (l > r) {
        return -INF;
    } else if (l == 0) {
        return max(QueryMax(l + 1, r), 0ll);
    } else {
        int k = lg[r - l + 1];
        return max(maxn[l][k], maxn[r - (1 << k) + 1][k]);
    }
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> q;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        lg[i] = log2(i), pre[i] = pre[i - 1] + a[i], minn[i][0] = maxn[i][0] = pre[i];
    }
    for (int j = 1; (1 << j) <= n; j++) {
        for (int i = 1; i + (1 << j) - 1 <= n; i++) {
            minn[i][j] = min(minn[i][j - 1], minn[i + (1 << (j - 1))][j - 1]);
            maxn[i][j] = max(maxn[i][j - 1], maxn[i + (1 << (j - 1))][j - 1]);
        }
    }
    for (int i = 1, x, y; i <= q; i++) {
        cin >> x >> y;
        cout << QueryMax(x - 1, y) - QueryMin(x - 1, y) << '\n';
    }

    return 0;
}

T4

Description

给定 n 个二元组 (ai,bi) ,求字典序最小的排列,使得相邻二元组之间的 a 或者 b 相同,且不能连续出现三个相同的二元组。

第一行一个自然数 n。 接下来 n 行,每行两个自然数 a,b

第一行一个字符串 YesNo ,表示是否存在方案。 如果存在方案,接下来一行 n 个自然数,第 i 个自然数表示第 i 个二元组。

1a,bn,2n5×105,保证不存在两个完全一样的二元组。

Solution

咕咕咕。

Code

咕咕咕。

Summary

需要掌握的:龙龙

posted @   PikachuQAQ  阅读(7)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示