先看题目:https://ac.nowcoder.com/acm/contest/5723/J
题目描述:
给出一些边长都为k的正方形的中心坐标,如果只有一对正方形重叠,则输出重叠面积,如果有多对正方形重叠,输出-1,如果没有正方形重叠,则输出0
解题思路:
画图模拟一下可知,如果两正方形中点坐标为(x1,y1)和(x2,y2),若|x1-x2| < k && |y1-y2| < k时,才能重叠,其重叠形成的矩形的面积为(k-|y1-y2|)*(k-|x1-x2|)
这道题普通n^2搜索是显然过不了的,但是可以思考思考做出优化。
这道题的n^2搜索

for(int i = 1; i < n; i++) {
    for(int j = i+1; j <= n; j++) {
           判断如果重叠,计算面积...
     }
}

但是我们发现,如果提前对矩形按x坐标排序,矩形i与i-1之间都是相邻关系了,实际上对这两个进行判断是否重叠就行了,如果不重叠就更不可能与之前的重叠了。

虽然也是两次循环,但实际上是O(n)

sort(a+1, a+n+1, cmp);
    for(int i = 2; i <= n; i++) {
        for(int j = i-1; j >= 1; j--) {
            判断如果重叠,计算面积...
        }
    }

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool vis[50100];
struct node{
    int x, y;
}a[50100];
bool cmp(node n, node m)
{
    return n.x < m.x;
}
int main()
{
    int n, k, tot=0;
    ll ans = 0;
    scanf("%d%d",&n,&k);
    for(int i = 1; i <= n; i++) {
        scanf("%d%d",&a[i].x,&a[i].y);
    }
    sort(a+1, a+n+1, cmp);
    for(int i = 2; i <= n; i++) {
        for(int j = i-1; j >= 1; j--) {
            int tmp = a[i].x - a[j].x;
            if(tmp  >= k) break;
            if(abs(a[i].x - a[j].x) < k && abs(a[i].y - a[j].y) < k)
            {
                tot++;
                vis[i] = 1; vis[j] = 1;
                ans += (k-abs(a[i].x - a[j].x))*(k-abs(a[i].y - a[j].y));
                if(tot == 2) {
                    printf("-1\n");
                    return 0;
                }
            }
        }
    }
    printf("%lld\n",ans);
}