codeforces #817(Div.4) E题解

 

E - Counting Rectangles

题意:给你n个长方形,并告诉你它们的长和宽(hi, wi),再给你两个长方形r1,r2,使得r1能够放置在长和宽均比它大长方形中,长方形中满足长和宽比r2小的能够放置在r2中(放置规则:长对长,宽对宽)。输出满足条件的长方形的面积和。
 
 
初始思路:建立了一个结构体数组,写了一个cmp排序函数,先根据h排序,h一样的话再根据w排序,然后从前往后筛flag1,从后往前筛flag2,中间的就是满足条件的。但是这样做是错误的,因为位于(flag1, flag2)中的矩形只有h是满足条件的,w不一定满足条件,有可能比w1小,也有可能比w2大。这样做得到的并不是正解。于是,我需要在(flag1,flag2)中筛出满足w1 < wi < w2 的矩形。这样得到的才是对的答案,然而这样做T了。
 
看了大佬的题解,这个题原来是一个可以转化为二维前缀和的题目。
 
正解(咳咳)
把所有矩形都在左上角(0,0)对齐,这样矩形的长和宽就很好看了;
建立一个二维数组a,即前缀和数组;
初始化a[ i ][ j ], 初始数值表示 起点在(0,0),对角在(i,j)的矩形 的面积;
然后进行前缀和预处理,得到的a[ i ][ j ]代表长和宽分别 <= i, j 的矩形的面积和;
只有满足长宽均大于第一个矩形且小于第二个矩形的矩形才是我们想要的,即对角点能落在某个区间的矩形,即下图斜线区。

 

在写前缀和加减操作的时候,一定要注意边界的范围,标红的这部分真的很容易写错,还不好发现;
ll re = a[h2 - 1][w2 - 1] - a[h1][w2 - 1] - a[h2 - 1][w1] + a[h1][w1];
最后记得开long long
AC路上无捷径啊,每一个细节都要注意。
 
AC代码:
 
复制代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1050;
ll a[maxn][maxn];
int n, q;

void solve() {
    memset(a, 0, sizeof(a));
    cin >> n >> q;
    for (int i = 1; i <= n; i ++) {
        int h, w;
        cin >> h >> w;
        a[h][w] += (ll)h * w;
    }
    n = 1e3;
    for (int i = 1; i <= n; i ++) 
        for (int j = 1; j <= n; j ++) 
            a[i][j] += a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];
    
    for (int i = 1; i <= q; i ++) {
        int h1, w1, h2, w2;
        cin >> h1 >> w1 >> h2 >> w2;
        ll re = a[h2 - 1][w2 - 1] - a[h1][w2 - 1] - a[h2 - 1][w1] + a[h1][w1];
        cout << re << "\n";
    }

}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie();

    int t;
    cin >> t;
    while (t --) {
        solve();
    }

    return 0;
}
复制代码

 

 
 
posted @   Y2ZH  阅读(189)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示