1 条题解

  • 0
    @ 2025-8-24 22:27:04

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar SBofGaySchool
    SB of gay school BU PA anything!

    搬运于2025-08-24 22:27:04,当前版本为作者最后更新于2020-12-25 14:29:38,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    我来一发纯暴力的吧,不用什么树状数组,也不用(手动)离散化和前缀和,直接暴力肝就好。

    1. 思路

    显然,每行、每列都至多只有一个点。对行坐标排序,滤掉没有牛的行(这实际上相当于离散化)。设 a[i]a[i] 代表第 ii 行的那头牛所在的列坐标。

    考虑下侧木板在第 ii 行,上侧木板在第 jj 行的情况。为了避免相同情况重复计算(即围栏形状不同,但圈住的牛相同),第 ii 行的牛和第 jj 行的牛必须被圈住

    • 如果第 jj 行的牛在第 ii 行的牛左边(即 a[i]>a[j]a[i] > a[j]):

      • 任何一头在 ii 行与第 jj 行之间,在第 jj 行的牛左边 的牛,即满足 i<k<j,a[k]<a[j]i<k<j,a[k]<a[j]kk,都可以作为左侧围栏所在位置的选项(如果不满足此条件,则第 jj 行的牛无法被圈住);当然,第 jj 行的牛本身(a[j]a[j])也可以作为左侧围栏所在位置的选项。

      • 任何一头在 ii 行与第 jj 行之间,在第 ii 行的牛右边 的牛,即满足 i<k<j,a[k]>a[i]i<k<j,a[k]>a[i]kk,都可以作为右侧围栏所在位置的选项(如果不满足此条件,则第 ii 行的牛无法被圈住);当然,第 ii 行的牛本身(a[i]a[i])也可以作为右侧围栏所在位置的选项。

    • jj 行的牛在第 ii 行的牛右边(即 a[i]<a[j]a[i] < a[j])的情况同理。

    所以,下侧木板在第 ii 行,上侧木板在第 jj 行的所有可能,即为 左侧围栏选项总数 ×\times 右侧围栏选项总数

    我们只需在枚举 i,ji,j 的过程中,维护:

    • 对于第 ii 行的牛,在第 ii 行与第 jj 行之间,有多少头牛在它的左边/右边;
    • 对于第 jj 行的牛,有第 ii 行与第 jj 行之间,有多少头牛在它的左边/右边;

    顺带累加答案,即可轻松完成此题。

    时间复杂度为 O(N2)O(N^2)

    2. 代码实现

    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    #define MAXN 2505
    ll N;
    // 每头牛的行/列坐标
    pair<ll, ll> x[MAXN];
    // 先算上空集
    ll ans = 1;
    // l[j]代表【第j行的牛】与【当前第i行的牛】之间,有多少头牛在【第j行的牛】左边
    // r[j]同理
    ll l[MAXN], r[MAXN];
    int main() {
        cin >> N;
        for (int i = 0; i < N; i++)
            cin >> x[i].first >> x[i].second;
        // 按行坐标排序
        sort(x, x + N);
        // 枚举i
        for (ll i = 0; i < N; i++) {
            ans++;
            // lt代表【第i行的牛】与【当前第j行的牛】之间,有多少头牛在【第i行的牛】左边
            // rt同理
            ll lt = 0, rt = 0;
            for (ll j = i - 1; j >= 0; j--) {
                // 根据【第i行的牛】与【第j行的牛】的相对位置,累加答案,更新计数
                if (x[i].second > x[j].second) {
                    ans += (rt + 1) * (l[j] + 1);
                    r[j]++;
                    lt++;
                } else {
                    ans += (lt + 1) * (r[j] + 1);
                    l[j]++;
                    rt++;
                }
            }
        }
        cout << ans << endl;
        return 0;
    }
    
    • 1

    信息

    ID
    6339
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者