티스토리 뷰

[Codeforces 1041D] Glider - 1700


문제 설명 : 

높이가 h인 공중에서 글라이더를 날린다. 글라이더를 날려 보내기 시작하는 지점은 상관없다. 기본적으로 글라이더는 낙하하면서 고도가 1미터 낮아질 때마다 앞으로 1미터씩 비행하는데, 상승기류가 존재하는 구간이 있어서 그 구간에서는 글라이더의 고도가 낮아지지 않으면서 앞으로 1미터씩 비행한다. 이때 글라이더가 비행을 시작한 시점부터 땅에 닿기까지 최대로 비행할 수 있는 거리를 구하는 문제이다.


풀이 :

두 가지 풀이가 있는데 하나는 이분탐색, 다른 하나는 투포인터이다. 처음에 내가 떠올린 풀이는 투포인터였는데 구현이 꼬여서 우선 이분탐색으로 푼 다음에 다시 투포인터로 풀었다. 문제에서 글라이더의 고도가 0이 되기 전까지는 계속 1미터씩 비행할 수 있으므로, 언제부터(어느 지점부터) 비행을 시작해야 오랫동안 날 수 있는지를 구해야한다. 단순 낙하하는 케이스의 경우 어느 지점에서든지 고도 1미터당 거리 1미터씩 비행하므로 이는 고려할 필요가 없다. 내가 신경써야 할 것은 상승기류 구간에서 최대한 오랫동안 비행하는 것이다. 즉 높이 h에서 낙하기 시작하면서 얼마나 길게 상승기류 구간을 지날 수 있는지가 관건이다. 


투포인터 풀이 :

(어떤 상승기류의 끝점~다음 상승기류의 시작점) 사이의 거리에서는 낙하할 수 밖에 없다. 그래서 먼저 상승기류간의 거리 차이들을 누적합 형태로 배열에 저장한다(=gap[]). 그리고 높이 h를 초과하지 않는 한도 내에서 방금 구한 거리 차이들을 넓혀나가면서(=gap[j]-gap[i]), 동시에 상승기류 구간의 길이도 같이 더한다(=cur_sum). 더이상 넓힐 수 없다면 그 동안 저장된 구간의 합의 최대값을 저장하기 위해 ans와 비교연산한다. 이 시행이 끝나고 나면 cur_sum에 dist[i]를 빼고 다음 구간인 [i+1]로 넘어가서 (가능하다면) 오른쪽 범위를 넓혀나간다.


이분탐색 풀이 : 

현재 지점에서 h의 거리 안에 속하면서 좌표가 가장 큰 상승기류의 구간을 찾는다. 그 지점까지의 구간 길이들의 합을 더해서 ans값과 비교하여 갱신한다.



주의할 점 : 

-


배울 점 : 

투포인터를 구현하는 부분은 아직 더 연습을 해야겠다.


코드 :

 

(투포인터 풀이)

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
#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;
struct S{
    int a,b;
 
    S(){}
    S(int _a,int _b){
        a=_a;
        b=_b;
    }
 
    const bool operator<(const S &o) const{
        return a<o.a;
    }
};
priority_queue<int,vector<int>,greater<int>> mpq;
 
inline void showAll(vector<int> &v,int NL_or_space=0){ 
    //0 is space(default), 1 is NL
    for(int &here:v){
        printf("%d",here);
        printf("%c",(NL_or_space)?'\n':' ');
    }
}
/*********************Contest Template***********************/
const int SIZE= 200009;
 
pii arr[SIZE];
int gap[SIZE];
int dist[SIZE];
 
int main(){
    int n,h;    scanf("%d %d",&n,&h);
 
    for(int i=1 ; i<=n ; i++){
        int x1,x2;  scanf("%d %d",&x1,&x2);
        arr[i]={x1,x2};
        gap[i]=gap[i-1]+(arr[i].first-arr[i-1].second);
        dist[i]=x2-x1;
    }
 
    ll ans=0;
    ll cur_sum=0;
    for(int i=1,j=1 ; i<=n ; i++){
        while(gap[j]-gap[i] <&& j<=n){
            cur_sum+=dist[j];
            j++;
        }
 
        ans=max(ans,cur_sum);
        cur_sum-=dist[i];
    }
    
    ans+=h;
    printf("%lld\n",ans);
    return 0;
}
 
cs



(이분탐색 풀이)

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
#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;
struct S{
    int a,b;
 
    S(){}
    S(int _a,int _b){
        a=_a;
        b=_b;
    }
 
    const bool operator<(const S &o) const{
        return a<o.a;
    }
};
priority_queue<int,vector<int>,greater<int>> mpq;
 
inline void showAll(vector<int> &v,int NL_or_space=0){ 
    //0 is space(default), 1 is NL
    for(int &here:v){
        printf("%d",here);
        printf("%c",(NL_or_space)?'\n':' ');
    }
}
/*********************Contest Template***********************/
const int SIZE= 200009;
 
pii arr[SIZE];
int gap[SIZE],dist[SIZE];
ll gap_sum[SIZE],dist_sum[SIZE];
 
int main(){
    int n,h;    scanf("%d %d",&n,&h);
 
    for(int i=1 ; i<=n ; i++){
        int x1,x2;  scanf("%d %d",&x1,&x2);
        arr[i]={x1,x2};
        dist[i]=x2-x1;
        if(i==1) gap[i]=0;
        else gap[i]=x1-arr[i-1].second;
        dist_sum[i]=dist_sum[i-1]+dist[i];
        gap_sum[i]=gap_sum[i-1]+gap[i];
    }
 
    ll ans=0;
    for(int i=1 ; i<=n ; i++){
        int l=i-1,r=n+1,mid;
        ll find=gap_sum[i]+h;
        while(l+1<r){
            mid=(l+r)/2;
 
            if(gap_sum[mid]>=find)
                r=mid;
            else l=mid;
 
        }
        ans=max(ans,dist_sum[l]-dist_sum[i-1]);
    }
    ans+=h;
    printf("%lld\n",ans);
 
 
 
    return 0;
    
}
 
cs


'Problem Solving > Binary Search' 카테고리의 다른 글

[CF 1400D] Zigzags  (0) 2021.10.15
[Codeforces 1148B] Born This Way  (0) 2019.06.12
[Codeforces 1073C] Vasya and Robot  (0) 2019.05.04
[Codeforces 1138C] Skyscrapers  (0) 2019.03.13
댓글