1 条题解

  • 1
    @ 2023-10-09 16:54:01

    ⾸先的⼀个性质:4个区间⾯积的情况相等,直接计算⼀个区域最后将答案 × 4 就可以了。

    40%的做法:

    考虑坐标的⼤⼩,整个能覆盖到的范围不超过 \(3333 \times 3333\),也就是答案⼤⼩不超过这么多。我们可以考虑判断 \(3333 \times 3333\) 中的每个点是否包含某在⼀个矩阵中。
    判断的⽅法:对 \((x_i, y_i)\) 点对按照 \(x_i\) 进⾏排序,可以使⽤⼀个 vector 来记录能够覆盖到 \(x_i\) 的 \(y_i\) 有哪些。对每个点的查询都可以先⼆分 \(x_i\) ,找到能覆盖这个点最⼩的 \(x\) ,并查询能覆盖这个 \(x\) 最⼤的 \(y\) 是多少(这⾥可以发现记录 \(y\) 的 vector 可以舍弃,直接记录最⼤值的 \(y\) 即可)。

    额外10%的做法:

    没有包含的情况,那么所有的矩阵⼀定满⾜形式:以⼀个递降的形式。可以直接计算每⼀个矩阵相对于之前多出来的部分。

    100%的做法:

    发现有包含的情况也可以⽤类似的⽅法来做,只不过需要排除掉包含的情况。
    对于 \(n \leqslant 10^6\) ,排除的⽅法可以使⽤⼆维数点的⽅式:对每个点查询左上⻆是否有其他的点,可以使⽤树状数组来实现。

    #include <bits/stdc++.h>
    #define mk make_pair
    #define x first
    #define y second
    using namespace std;
    const int maxn = 1e6 + 10;
    int n;
    pair<int, int> a[maxn];
    int Rank[maxn];
    long long ans;
    struct TA {
        int tr[maxn];
    
      TA() {
            memset(tr, 0, sizeof tr);
        }
    
        void update(int x) {
            while(x <= n) ++tr[x], x += x & -x;
        }
    
        int query(int x) {
            int tot = 0;
            while(x) tot += tr[x], x -= x & -x;
            return tot;
        }
    }T;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(NULL);
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> a[i].x >> a[i].y;
            a[i].x /= 2, a[i].y /= 2;
            Rank[i] = a[i].y;
        }
        sort(a + 1, a + 1 + n);
        sort(Rank + 1, Rank + 1 + n);
        int Maxy = 0;
        for(int i = n; i > 0; --i) {
            int id = lower_bound(Rank + 1, Rank + 1 + n, a[i].y) - Rank;
            T.update(id);
            if(n - i - T.query(id) + 1 > 0) continue; //⼆维数点判断
            ans += 1ll * (a[i].y - Maxy) * a[i].x;
            Maxy = a[i].y;
        }
        cout << ans * 4 << '\n';
        return 0;
    }
    

    当然,观察最后形成的范围,都会是⼀段⼀段的,且是⼀个递降的形式。我们可以按照坐标从⼤往⼩考虑,直接维护每个坐标的⾼度,也可以获得答案。

    #include <bits/stdc++.h>
    using namespace std;
    int n, Mx[10000010];
    long long ans;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(NULL);
        cin >> n;
        for (int x, y, i = 1; i <= n; i++) {
            cin >> x >> y;
            x /= 2, y /= 2;
            Mx[x] = max(Mx[x], y);
        }
        for (int h = 0, i = 10000000; i >= 1; i--) {
            h = max(h, Mx[i]);
            ans += h;
        }
        cout << ans * 4 << '\n';
        return 0;
    }
    
  • 1

信息

ID
1011
难度
5
分类
树状数组 点击显示
标签
递交数
5
已通过
3
通过率
60%
上传者