P7153 [USACO20DEC] Square Pasture G 题解

传送门

对于每种集合只考虑包含这些点的最小的正方形,这样就不会多算。对于一个正方形,如果两条邻边上都没有奶牛,那就可以将边长减一。

考虑左边和上面的两条边。

$1.$ 如果两边上都有奶牛:

可以枚举左上角的点,然后对每个能覆盖到的点求出覆盖这个点最短的正方形的边长,最后对这些边长去个重,统计一下有多少个合法即可,时间复杂度 $O(n^3\log n)$。


$2.$ 如果两边上只有一边有奶牛:

下面假设是左侧边上没有奶牛,上边没有奶牛的情况类似处理。

那么底边一定也有奶牛,枚举这两条边的纵坐标,那么正方形的边长就知道了。考虑一个左侧边上没有奶牛的正方形,如果向右移一格覆盖到的奶牛集合不变,那这个正方形就不对答案有贡献。

于是可以枚举右侧边的横坐标,其横坐标加一一定是一个点的横坐标,时间复杂度 $O(n^3\log n)$。

参考代码:

#include<bits/stdc++.h>
#define ll long long
#define mxn 200003
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rept(i,a,b) for(int i=a;i<b;++i)
using namespace std;
struct node{
    int x,y;
}a[203];
int n,t,ans,d[203],d1[203],d2[203],p1[203],p2[203];
set<int>s;
map<int,bool>mp;
signed main(){
    scanf("%d",&n);
    rep(i,1,n)scanf("%d%d",&a[i].x,&a[i].y),d1[i]=a[i].x,d2[i]=a[i].y;
    sort(d1+1,d1+n+1);
    sort(d2+1,d2+n+1);
    rep(i,1,n){
        p1[lower_bound(d1+1,d1+n+1,a[i].x)-d1]=i;
        p2[lower_bound(d2+1,d2+n+1,a[i].y)-d2]=i;
    }
    rep(i,1,n){
        rep(j,1,n)if(a[p1[i]].y>=d2[j]&&a[p2[j]].x>=d1[i]){
            s.clear();
            rep(k,1,n)if(a[k].x>=d1[i]&&a[k].y>=d2[j])s.insert(max(a[k].x-d1[i],a[k].y-d2[j]));
            for(int k:s)if(k>=max(a[p1[i]].y-d2[j],a[p2[j]].x-d1[i]))ans++;
        }
    }
    d[0]=-2e9;
    rept(i,1,n){
        rep(j,i+1,n){
            int y1=a[p1[i]].y,y2=a[p1[j]].y,ds=d1[j]-d1[i];
            if(y1>y2)swap(y1,y2);
            if(y2-y1>ds)continue;
            t=0;
            mp.clear();
            rep(k,1,n)if(a[p2[k]].x>=d1[i]&&a[p2[k]].x<=d1[j])d[++t]=d2[k],mp[d2[k]]=1;
            int e2=lower_bound(d+1,d+t+1,y2)-d;
            rep(k,e2+1,t){
                if(d[k]-1-ds>=y1)break;
                if(mp.find(d[k]-1-ds)==mp.end())ans++;
            }
        }
    }
    rept(i,1,n){
        rep(j,i+1,n){
            int y1=a[p2[i]].x,y2=a[p2[j]].x,ds=d2[j]-d2[i];
            if(y1>y2)swap(y1,y2);
            if(y2-y1>ds)continue;
            t=0;
            mp.clear();
            rep(k,1,n)if(a[p1[k]].y>=d2[i]&&a[p1[k]].y<=d2[j])d[++t]=d1[k],mp[d1[k]]=1;
            int e2=lower_bound(d+1,d+t+1,y2)-d;
            rep(k,e2+1,t){
                if(d[k]-1-ds>=y1)break;
                if(mp.find(d[k]-1-ds)==mp.end())ans++;
            }
        }
    }
    cout<<ans+1;
    return 0;
}
posted @ 2023-11-25 19:08  zifanwang  阅读(9)  评论(0编辑  收藏  举报  来源