티스토리 뷰
[Codeforces 1028C] Rectangles - 1600
문제 설명 :
n개의 직사각형의 좌표가 주어진다. n개의 직사각형중에서 최소 (n-1)개의 직사각형의 교집합의 좌표를 구하면 된다.
풀이 :
최소 (n-1)개의 직사각형의 교집합을 구해야 한다. 이는 다른 말로 표현하면 포함하지 않을 단 1개의 직사각형을 고르면 된다는 뜻이다. n개의 직사각형을 모두 살펴보면서 현재 보는 직사각형을 포함하지 않으면 나머지 (n-1)개의 직사각형들은 교집합을 가질 수 있는지 확인하면 된다. 확인하는 연산은 단 O(1)만에 가능하다. 전처리로 1~i까지의 직사각형의 교집합을 저장하는 pref[]배열, (i+1)~n까지 직사각형의 교집합을 저장하는 suf[]배열을 만들어놓고 1~(i-1)범위의 교집합( = pref[i-1] )과 (i+1)~n범위의 교집합( = suf[i+1] )이 서로 교집합이 있는지 살펴보면 된다. 두 직사각형의 교집합 판별 여부는 예전의 reference로 작성한 적이 있고 아래 코드의 83줄에 자세히 나와있다.
주의할 점 :
원래는 x1<x2, y1<y2가 만족되어야만 유효한 직사각형 좌표라고 할 수 있는데 두 직사각형간에 교집합이 없으면 x1>x2, y1>y2 형태로 저장된다. 이렇게 저장되면 다른 직사각형과의 교집합을 구할 때도 계속 이런 형태로 저장된다.
배운 점 :
처음에 풀 때는 포함시킬 (n-1)개의 직사각형에 포커스를 맞췄는데, 반대로 생각해서 포함하지 않을 1개의 직사각형만 고려하면 쉽게 풀 수 있다. 그리고 전처리로 pref,suf배열을 이용하면 O(1)만에 구할 수도 있다.
코드 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | #include<stdio.h> #include<math.h> #include<string.h> #include<iostream> #include<functional> #include<string> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<assert.h> #include<stdlib.h> #include<stack> using namespace std; /*********************Contest Template***********************/ typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<long long,long long> pll; typedef pair<int,int> Cord; #define FASTIO ios_base::sync_with_stdio(false);cin.tie(0); struct Rec{ int x1,y1,x2,y2; Rec(){} Rec(int _x1,int _y1,int _x2,int _y2){ x1=_x1,y1=_y1,x2=_x2,y2=_y2; } // const bool operator<(const S &o) const{ // return a<o.a; // } }; priority_queue<int,vector<int>,greater<int>> mpq; #define SPACE 0 #define NL 1 inline void showAll(vector<int> &v,int NL_or_space){ //0 is space, 1 is NL for(int &here:v){ printf("%d",here); printf("%c",(NL_or_space)?'\n':' '); } } /*********************Contest Template***********************/ const int SIZE= 140009; const int INF=1<<30; Rec arr[SIZE],pref[SIZE],suf[SIZE]; int main(){ int n; scanf("%d",&n); for(int i=1 ; i<=n ; i++){ int a,b,c,d; scanf("%d %d %d %d",&a,&b,&c,&d); arr[i]=Rec(a,b,c,d); } pref[0]=Rec(-INF,-INF,INF,INF); suf[n+1]=Rec(-INF,-INF,INF,INF); pref[1]=arr[1]; suf[n]=arr[n]; for(int i=2 ; i<=n ; i++){ int x1=arr[i].x1,x2=arr[i].x2,y1=arr[i].y1,y2=arr[i].y2; int a1=pref[i-1].x1,a2=pref[i-1].x2,b1=pref[i-1].y1,b2=pref[i-1].y2; pref[i].x1=max(x1,a1), pref[i].x2=min(x2,a2), pref[i].y1=max(y1,b1), pref[i].y2=min(y2,b2); } for(int i=n-1 ; i ; i--){ int x1=arr[i].x1,x2=arr[i].x2,y1=arr[i].y1,y2=arr[i].y2; int a1=suf[i+1].x1,a2=suf[i+1].x2,b1=suf[i+1].y1,b2=suf[i+1].y2; suf[i].x1=max(x1,a1), suf[i].x2=min(x2,a2), suf[i].y1=max(y1,b1), suf[i].y2=min(y2,b2); } for(int i=1 ; i<=n ; i++){ int x1=pref[i-1].x1,x2=pref[i-1].x2,y1=pref[i-1].y1,y2=pref[i-1].y2; int a1=suf[i+1].x1,a2=suf[i+1].x2,b1=suf[i+1].y1,b2=suf[i+1].y2; if(max(x1,a1)<=min(x2,a2) && max(y1,b1)<=min(y2,b2)){ printf("%d %d\n",max(x1,a1),max(y1,b1)); return 0; } } assert(0); } | cs |
'Problem Solving > Geometry' 카테고리의 다른 글
[CF 1163C2] Power Transmission (Hard Edition) (0) | 2019.09.22 |
---|