2022 Benelux Algorithm Programming Contest (BAPC 22) A 、I、J、L题解

A. Adjusted Average(暴力枚举+二分查找)

分析

读完题目可以发现k很小,那么考虑暴力做法的时间复杂度为O(Cnk),对于k3的其实可以直接暴力创过去,但对于k=4的情况显然不适用。那么对应k=4的情况考虑优化,可以选择将数分为两个集合,先用一个set存下其中一个集合的所有选择方案,此时枚举删除另外一个集合中的哪两个数,最后二分查找最优的匹配方案。时间复杂度O(n2logn)

代码实现

#include <bits/stdc++.h>
int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    #define int long long
    int n, k, x;
    std::cin >> n >> k >> x;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> a[i];
    }
    int sum = std::accumulate(a.begin(), a.end(), 0LL);
    double ans = abs((double)sum / n - x);
    for (int num = 1; num <= k; ++num) {
        std::set<int> st{(int)-1e18, (int)1E18};
        for (int i = 0; i < n; ++i) {
            ans = std::min(ans, abs((double)(sum - a[i]) / (n - 1) - x));
            if (num == 1) continue;
            for (int j = i + 1; j < n; ++j) {
                ans = std::min(ans, abs((double)(sum - a[i] - a[j]) / (n - 2) - x));
                if (num == 2) continue;
                int sur = sum - (n - num) * x - a[i] - a[j];
                auto it = st.lower_bound(sur);
                ans = std::min({ans, abs((double)(sur - *it) / (n - num)), abs((double)(sur - *(--it)) / (n - num))});
            }
            for (int j = 0; j < i; ++j) {
                st.emplace(a[i] + a[j] * (num == 4));
            }
            if (num == 3) st.emplace(a[i]);
        }
    }
    std::cout << ans << '\n';
}

原题在这里(╹▽╹)

I - Imperfect Imperial Units(离散化)

分析

正解应该是从每个点开始搜一遍,但是写的时候偷懒,于是魔改了一下Floyd创过去了。时间复杂度O(n3+q)

代码实现

#include <bits/stdc++.h>
int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    std::cout << std::setprecision(12);
    int n, m;
    std::cin >> n >> m;
    std::map<std::string, int> mp;
    std::vector<std::tuple<double, int, int>> edges;
    int cur = 0;
    for (int i = 0; i < n; ++i) {
        double a, b;
        std::string x, op, y;
        std::cin >> a >> x >> op >> b >> y;
        if (!mp.count(x)) mp[x] = cur++;
        if (!mp.count(y)) mp[y] = cur++;
        int u = mp[x], v = mp[y];
        edges.emplace_back(b, u, v);
        edges.emplace_back(a / b, v, u);
    }
    std::vector g(cur, std::vector<double>(cur, 1e305));
    std::vector f(cur, std::vector<int>(cur, 0)), cnt(cur, std::vector<int>(cur, 0));
    for (auto [c, a, b] : edges) {
        g[a][b] = c;
        g[a][a] = g[b][b] = 1;
        f[a][b] = f[a][a] = f[b][b] = 1;
    }
    for (int k = 0; k < cur; ++k) {
        for (int i = 0; i < cur; ++i) {
            for (int j = 0; j < cur; ++j) {
                f[i][j] |= f[i][k] & f[k][j];
                if (f[i][j] && !cnt[i][j]) {
                    cnt[i][j] += 1;
                    g[i][j] = std::min(g[i][k] * g[k][j], g[i][j]);
                }
            }
        }
    }
    while (m--) {
        double x;
        std::string a, op, b;
        std::cin >> x >> a >> op >> b;
        if (!mp.count(a) || !mp.count(b)) {
            std::cout << "impossible" << "\n";
        } else {
            int u = mp[a], v = mp[b];
            if (f[u][v]) {
                std::cout << g[u][v] * x << "\n";
            } else {
                std::cout << "impossible" << '\n';
            }
        }
    }
}

原题在这里(╹▽╹)

J. Jagged Skyline (随机化+二分)

分析

题目只给了12000次询问,显然如果每个点问过去次数显然是不够的。这边可以做个随机化问点,每次查询当前最高值+1,如果为sky那就直接跳过,否则说明当前的位置比我最大值要大,此时更新一下最大值。期望的询问次数大概是O(n+ln(w)log2(n))

代码实现

#include <bits/stdc++.h>
std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    #define int long long
    int n, h, cur = 11999;
    std::cin >> n >> h;
    std::vector<int> ord(n);
    std::iota(ord.begin(), ord.end(), 1);
    std::shuffle(ord.begin(), ord.end(), std::default_random_engine(rng()));
    auto get = [&](int w, int high) {
        std::cout << "! " << w << ' ' << high << std::endl;
        exit(0);
    };
    auto ask = [&](int W, int H) {
        cur--;
        std::cout << "? " << W << " " << H << std::endl;
        std::string x;
        std::cin >> x;
        return x;
    };
    int max = 0, pos = 1;
    for (int i = 0; i < n; ++i) {
        if (ask(ord[i], max + 1) != "sky") {
            if (cur == 0) get(pos, max);
            if (ask(ord[i], h) == "building") get(ord[i], h);
            int l = max + 1, r = h;
            while (l < r) {
                int mid = l + r >> 1;
                if (ask(ord[i], mid) == "sky") {
                    r = mid;
                } else {
                    l = mid + 1;
                }
                if (cur == 0) get(pos, max);
            }
            if (l - 1 > max) {
                pos = ord[i], max = l - 1;
                if (max == h) get(pos, max);
            }
        }
    }
    get(pos, max);
}

原题在这里(╹▽╹)

L. Lowest Latency (三维最近点对)

分析

这题不知道是水还是怎么的,贴了一个二维最近点对的代码就创过去了。

代码实现

#include <bits/stdc++.h>

using namespace std;
using DB = long double;

const DB eps = 1e-12, inf = 1e100, pi = acos(-1);
DB dcmp(DB x, DB y) { return fabs(x - y) < eps ? 0 : x < y ? -1 : 1; }
DB sgn(DB x) { return fabs(x) < 0 ? 0 : x < 0 ? -1 : 1; }
DB rand_eps() { return ((DB)rand() / RAND_MAX - 0.5) * eps; }
struct Point3 {
    DB x, y, z;
    Point3 () {}
    Point3 (DB x, DB y, DB z) : x(x), y(y), z(z) {}
    void shake() { x += rand_eps(), y += rand_eps(), z += rand_eps(); }
    Point3 operator+(const Point3 &P) const { return Point3(x + P.x, y + P.y, z + P.z); }
    Point3 operator-(const Point3 &P) const { return Point3(x - P.x, y - P.y, z - P.z); }
    Point3 operator*(DB p) const { return Point3(x * p, y * p, z * p); }
    Point3 operator/(DB p) const { return Point3(x / p, y / p, z / p); }
    DB operator&(const Point3 &P) const { return x * P.x + y * P.y + z * P.z; }
    Point3 operator^(const Point3 &P) const { return Point3(y * P.z - z - P.y, z * P.x - x * P.z, x * P.y - y * P.x); }
    friend istream &operator>>(istream &is, Point3 &rhs) { return is >> rhs.x >> rhs.y >> rhs.z; }
    friend ostream &operator<<(ostream &os, const Point3 &rhs) { return os << '(' << rhs.x << ',' << rhs.y << ',' << rhs.z << ')'; }
};
using Vector3 = Point3;
DB Len(const Vector3 &A) { return sqrt(A & A); }
DB Len2(const Vector3 &A) { return A & A; }
DB Distance(const Vector3 &A, const Vector3 &B) { return Len(A - B); }
DB Closest_pair(const vector<Point3> &p, int l, int r) { // 平面最近点对
    DB dist = inf;
    if (l == r) return dist;
    if (l + 1 == r) return Distance(p[l], p[r]);
    int mid = l + r >> 1;
    DB d1 = Closest_pair(p, l, mid), d2 = Closest_pair(p, mid + 1, r);
    dist = min(d1, d2);
    vector<Point3> tmp;
    for (int i = l; i <= r; ++i)
        if (fabs(p[mid].x - p[i].x) <= dist) tmp.push_back(p[i]);
    for (int i = 0; i < tmp.size(); ++i) {
        for (int j = i + 1; j < tmp.size(); ++j) {
            // if (fabs(tmp[j].y - tmp[i].y) >= dist || fabs(tmp[j].z - tmp[i].z) >= dist) break;
            dist = min(dist, Distance(tmp[i], tmp[j]));
        }
    }
    return dist;
}
int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    std::cout << std::fixed << std::setprecision(20) << "\n";
    int n;
    std::cin >> n;
    std::vector<Point3> p(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> p[i];
    }
    std::sort(p.begin(), p.end(), 
        [&](const Point3& a, const Point3& b) {
            if (a.x == b.x) {
                if (a.y == b.y) {
                    return a.z < b.z;
                } else {
                    return a.y < b.y;
                }
            } else {
                return a.x < b.x;
            }
        });
    std::cout << Closest_pair(p, 0, n - 1) << "\n";
}

原题在这里(╹▽╹)

posted @   sleeeeeping  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
  1. 1 吹梦到西洲 恋恋故人难,黄诗扶,妖扬
  2. 2 敢归云间宿 三无Marblue
吹梦到西洲 - 恋恋故人难,黄诗扶,妖扬
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 颀鞍

作曲 : 铃木航海

编曲 : 远藤直弥/冯帆

制作人 : 冯帆/铃木航海

(妖扬)

(妖扬)

无何化有 感物知春秋

秋毫濡沫欲绸缪 搦管相留

(黄诗扶)

留骨攒峰 留容映水秀

留观四时曾邂逅 佳人西洲

(妖扬)

(妖扬)

西洲何有 远树平高丘

云闲方外雨不收 稚子牵牛

(黄诗扶)

闹市无声 百态阴晴栩栩侔

藤衣半卷苔衣皱 岁月自无忧

(妖扬)

(妖扬)

驾马驱车 尚几程扶摇入画中 咫尺

(黄诗扶)

径曲桥横 精诚难通

(黄诗扶、妖扬)

(黄诗扶、妖扬)

盼你渡口 待你桥头

松香接地走

挥癯龙绣虎出怀袖

起微石落海连波动

描数曲箜篌线同轴

勒笔烟直大漠 沧浪盘虬

一纸淋漓漫点方圆透

记我 长风万里绕指未相勾

形生意成 此意 逍遥不游

(妖扬)

(妖扬)

日月何寿 江海滴更漏

爱向人间借朝暮 悲喜为酬

(黄诗扶)

种柳春莺 知它风尘不可救

绵绵更在三生后 谁隔世读关鸠

(妖扬)

(妖扬)

诗说红豆 遍南国未见人长久 见多少

(黄诗扶)

来时芳华 去时白头

(黄诗扶、妖扬)

(黄诗扶、妖扬)

忘你不舍 寻你不休

画外人易朽

似浓淡相间色相构

染冰雪先披琉璃胄

蘸朱紫将登金银楼

天命碧城灰土 刀弓褐锈

举手夜古泼断青蓝右

照我 萤灯嫁昼只影归洪流

身魂如寄 此世 逍遥不游

(黄诗扶)

(黄诗扶)

情一物 无木成林无水行舟

情一事 未算藏谋真还谬

情一人 积深不厚积年不旧

情一念 墨尽非空 百代飞白骤 划地为囚

(妖扬)

(妖扬)

蓝田需汲酒 惟琼浆能浇美玉瘦

至高者清难垢 至贵者润因愁

痴竭火 知她不能求

醉逢歌 知他不必候

只约灵犀过隙灵光暗相投

(黄诗扶、妖扬)

(黄诗扶、妖扬)

万籁停吹奏

支颐听秋水问蜉蝣

既玄冥不可量北斗

却何信相思最温柔

顾盼花发鸿蒙 怦然而梦

你与二十八宿皆回眸

系我 彩翼鲸尾红丝天地周

情之所至 此心 逍遥不游

吉他 : ShadOw

钢琴 : ShadOw

和声编写 : 冯帆

和声 : 黄诗扶

人声混音 : 徐志明

混音 : 冯帆

母带 : 冯帆

企划 : 三糙文化

出品公司 : Negia Entertainment Inc.

点击右上角即可分享
微信分享提示