牛客周赛 Round 109 题解(简)

A 小红的直角三角形

两个点分别落在 轴和 轴上即可。

void solve() {
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    if (x1 == 0 && y1 != 0 && x2 != 0 && y2 == 0 || x1 != 0 && y1 == 0 && x2 == 0 && y2 != 0) cout << "Yes" << "\n";
    else cout << "No" << "\n";
}

B 小红的好点对

一看只有100个点,直接暴力枚举即可。

void solve() {
    int n;
    cin >> n;
    vector<PII> p(n);
    for (int i = 0; i < n; ++i) cin >> p[i].fi >> p[i].se;
    int ans = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            int dx = p[i].fi - p[j].fi, dy = p[i].se - p[j].se;
            if (dx * dx + dy * dy == 1) ans++;
        }
    }
    cout << ans << "\n";
}

C 小红的整数三角形

分两类讨论:

  • 1.两点 坐标相同上,即 ,显然可以取一个与连线距离为 的点,此时面积为 ,为整数。
  • 2.两点坐标不同,我们可以用 铅锤高 水平宽 来计算面积,也就是把三角形拆成两个直角三角形。根据已有的两点构造出直角三角形(即取 ),此时面积为 ,若已经为整数了,输出即可,否则再添上一个 即可。
void solve() {
    int x1, x2, y1, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    int dx = x1 - x2, dy = y1 - y2;
    if (dx != 0 && dy != 0) {
        if (dx * dy & 1) {
            cout << x1 + 1 << " " << y2 << "\n";
        } else {
            cout << x1 << " " << y2 << " ";
        }
    } else {
        if (dx == 0) {
            cout << x1 + 2 << " " << y1 << "\n";
        } else {
            cout << x1 << " " << y1 + 2 << "\n";
        }
    }
}

D 小红的马

对于每一个兵,标记可达它的周围8个点,最后找出标记次数最多的即为答案。

int dx[] = { -1, 1, -2, -2, -1, 1, 2, 2}, dy[] = {2, 2, 1, -1, -2, -2, 1, -1};
 
void solve() {
    const ll len = 2e5;
    int n;
    cin >> n;
    auto encode = [&](ll x, ll y) {
        return x * len + y;
    };
 
    map<ll, int> mp;
    for (int i = 0; i < n; ++i) {
        ll x, y;
        cin >> x >> y;
        for (int j = 0; j < 8; ++j) {
            if (x + dx[j] >= 1 && x + dx[j] <= len && y + dy[j] >= 1 && y + dy[j] <= len) mp[encode(x + dx[j], y + dy[j])]++;
        }
    }
    ll mx = 0, loc;
    for (auto [u, v] : mp) {
        if (v > mx) {
            mx = v;
            loc = u;
        }
    }
    cout << loc / len << " " << loc % len << "\n";
}

E 小红的好矩形

考虑容斥,答案即为

因为坐标范围给的很大,所以先要进行离散化(用map标记即可)。

void solve() {
    int n;
    cin >> n;
    vector<PII> p(n);
    map<int, map<int, int>> mp;
    map<int, vector<int>> X, Y;
    for (int i = 0; i < n; ++i) {
        int x, y;
        cin >> x >> y;
        p[i] = {x, y};
        mp[x][y] = 1;
        X[x].pb(y);
        Y[y].pb(x);
    }
    map<int, int> cnt1, cnt2;
    for (auto [u, v] : X) {
        for (auto vv : v) {
            if (mp[u + 1][vv]) cnt1[u]++;
        }
    }
    for (auto [u, v] : Y) {
        for (auto vv : v) {
            if (mp[vv][u + 1]) cnt2[u]++;
        }
    }
    ll ans = 0;
    for (auto [_, v] : cnt1) {
        ans += v * (v - 1) / 2;
    }
    for (auto [_, v] : cnt2) {
        ans += v * (v - 1) / 2;
    }
    sort(all(p));
    for (auto [x, y] : p) {
        if (mp[x + 1][y] && mp[x][y + 1] && mp[x + 1][y + 1]) ans--;
    }
    cout << ans << "\n";
}

F 小红的线下查询

先化公式,移一下项,得到

先取出 的部分,再在其中找 有多少个即可。

离线实现,借助了 的平衡树实现,需要注意 不能处理重复元素,所以需要用 打上重复标记。

void solve() {
    int n, q;
    cin >> n >> q;
    vector<PII> p(n);
    for (int i = 0; i < n; ++i) {
        int x, y;
        cin >> x >> y;
        p[i] = {y - x, y + x};
    }
    sort(all(p));
    vector<array<int, 3>> qs;
    for (int i = 0; i < q; ++i) {
        int k1, k2;
        cin >> k1 >> k2;
        qs.pb({k1, k2, i});
    }
    sort(all(qs));

    vector<int> ans(q);
    int ptr = 0;
    unordered_map<int, int> cnt;
    Tree tr;
    for (auto [k1, k2, i] : qs) {
        while (ptr < n && p[ptr].fi < k1) {
            tr.insert({p[ptr].se, cnt[p[ptr].se]});
            cnt[p[ptr].se]++;
            ++ptr;
        }
        ans[i] = tr.order_of_key({k2, 0});
    }
    for (auto v : ans) cout << v << "\n";
}

头文件参考

//Another
#include<bits/stdc++.h>
#include<bits/extc++.h>
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef tuple<ll, ll, ll> TLLL;
typedef __gnu_pbds::tree<PLL, __gnu_pbds::null_type, less<PLL>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update> Tree;
// typedef __gnu_pbds::tree<ll, __gnu_pbds::null_type, less<ll>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update> Tree;

constexpr int inf = (ll)1e9 + 7;
// constexpr ll INF = (ll)2e18 + 9;
constexpr ll INF = (ll)4e18;
// constexpr ll MOD = 1e9 + 7;
constexpr ll MOD = 998244353;
constexpr ld PI = acos(-1.0);
constexpr ld eps = 1e-10;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ull randint(ull l, ull r) {uniform_int_distribution<unsigned long long> dist(l, r); return dist(rng);}

void init() {

}

void solve() {
    
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    init();

    int t = 1;
    // cin >> t;
    for (int _ = 1; _ <= t; ++_) {
        solve();
    }
    return 0;
}