풀이

[백준] 20648 - Rectangular Pasture (c++)

땅왕 2025. 1. 28. 17:46

https://www.acmicpc.net/problem/20648

 

문제 요약

좌표평면에 있는 N마리의 소의 좌표가 주어진다. 

직사각형 모양의 울타리로 소를 가둘 계획이다. 울타리 하나로 가둘 수 있는 소의 집합의 개수를 구해라.

 

풀이 (N^2)

  • 누적합
  • 스위핑
  • 좌표 압축

N이 충분히 작기 때문에 N^2 풀이를 생각할 수 있다.

두 소 i,j를 고정시키고 그 소를 포함하는 최소 넓이의 직사각형을 구한다. 그 직사각형을 위 아래로 확장시키는 경우의 수(직사각형 위에 점*직사각형 아래에 점)를 구한다. 각 x,y가 고유하기 때문에 이렇게 만든 직사각형에 포함되는 소의 집합 또한 고유하다. i<j인 (i,j) 쌍에 대해 모두 구해주면 된다.

#include <bits/stdc++.h>
using namespace std;
#define ll long long

vector<int> xc,yc;
ll sum[3000][3000];

ll q(int sx,int sy,int ex,int ey) {
    return sum[ex][ey]-sum[ex][sy-1]-sum[sx-1][ey]+sum[sx-1][sy-1];
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    int n;cin>>n;
    vector<array<int,2>> v(n);
    for(auto& [x,y]:v)cin>>x>>y,xc.push_back(x),yc.push_back(y);
    sort(xc.begin(),xc.end());sort(yc.begin(),yc.end());
    for(auto& [x,y]:v) {
        x=lower_bound(xc.begin(),xc.end(),x)-xc.begin()+1;
        y=lower_bound(yc.begin(),yc.end(),y)-yc.begin()+1;
        sum[x][y]++;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
    ll ans=1+n;
    sort(v.begin(),v.end());
    for(int i=0;i<n;i++) {
        for(int j=i+1;j<n;j++) {
            auto [x1,y1]=v[i];
            auto [x2,y2]=v[j];
            if(y1>y2)
                swap(y1,y2);
            //cout<< q(x1,y2,x2,n)<< ' '<<q(x1,1,x2,y1)<<'\n';
            ans+=q(x1,y2,x2,n)*q(x1,0,x2,y1);    
        }
    }
    cout<<ans;
}