반응형

문제

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {1020, 10, 30, 20, 50} 이고, 길이는 4이다.

입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다.

둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000,000)

출력

 

첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.

 
예제 입력 1 
6
10 20 10 30 20 50
예제 출력 1 
4

8
10 20 30 5 10 20 30 40
정답: 5

반례 추가 
10
4 7 10 3 1 8 7 2 5 7
Answer: 4 
7
7 9 10 8 2 3 7
Answer: 3 
10
7 10 8 10 1 2 9 9 1 10
Answer: 4 
9
2 8 3 10 5 1 5 2 3
Answer: 3 
10
10 6 5 9 10 9 3 4 7 1
Answer: 3 
10
5 8 10 3 9 1 5 8 5 6
Answer: 3 
9
3 2 8 2 10 1 2 2 3
Answer: 3 
10
3 8 10 1 5 7 9 8 9 6
Answer: 5
7
4 3 4 9 1 3 7
Answer: 3 
10
8 6 8 9 5 1 4 4 6 3
Answer: 3

 

/*[12015]가장 긴 증가하는 부분 수열2*/
#include <bits/stdc++.h>
using namespace std;
#define MAXN ((int)1e6+10)
int N; 
int A[MAXN];
vector<int> v;
auto it = v.begin();
void InputData(){
    cin >> N;
    for(int i=0; i<N; i++){
        cin >> A[i];
    }
}
void Solve(){
    v.push_back(A[0]);
    for(int i=1; i<N; i++){
        if(v.back() < A[i] ) v.push_back(A[i]);
        else {
            it = v.begin();
            it = lower_bound(v.begin(), v.end(), A[i]);
            *it = A[i];
        } 
    }
    cout << v.size() << endl;
}
int main(){
    InputData();
    Solve();
    return 0;
}
/*[12015]가장 긴 증가하는 부분 수열2*/
반응형
반응형

문제

세준이는 크기가 N×N인 배열 A를 만들었다. 배열에 들어있는 수 A[i][j] = i×j 이다. 이 수를 일차원 배열 B에 넣으면 B의 크기는 N×N이 된다. B를 오름차순 정렬했을 때, B[k]를 구해보자.

배열 A와 B의 인덱스는 1부터 시작한다.

입력

첫째 줄에 배열의 크기 N이 주어진다. N은 105보다 작거나 같은 자연수이다. 둘째 줄에 k가 주어진다. k는 min(109, N2)보다 작거나 같은 자연수이다.

출력

B[k]를 출력한다.

예제 입력 1 
3
7
예제 출력 1 
6

 

3
7
i: 1 lo:1 hi : 7 mid: 4 tmp: 3
i: 2 lo:1 hi : 7 mid: 4 tmp: 5
i: 3 lo:1 hi : 7 mid: 4 tmp: 6
i: 1 lo:5 hi : 7 mid: 6 tmp: 3
i: 2 lo:5 hi : 7 mid: 6 tmp: 6
i: 3 lo:5 hi : 7 mid: 6 tmp: 8
i: 1 lo:5 hi : 5 mid: 5 tmp: 3
i: 2 lo:5 hi : 5 mid: 5 tmp: 5
i: 3 lo:5 hi : 5 mid: 5 tmp: 6
6

반응형
반응형

문제

도현이의 집 N개가 수직선 위에 있다. 각각의 집의 좌표는 x1, ..., xN이고, 집 여러개가 같은 좌표를 가지는 일은 없다.

도현이는 언제 어디서나 와이파이를 즐기기 위해서 집에 공유기 C개를 설치하려고 한다. 최대한 많은 곳에서 와이파이를 사용하려고 하기 때문에, 한 집에는 공유기를 하나만 설치할 수 있고, 가장 인접한 두 공유기 사이의 거리를 가능한 크게 하여 설치하려고 한다.

C개의 공유기를 N개의 집에 적당히 설치해서, 가장 인접한 두 공유기 사이의 거리를 최대로 하는 프로그램을 작성하시오.

 

입력

첫째 줄에 집의 개수 N (2 ≤ N ≤ 200,000)과 공유기의 개수 C (2 ≤ C ≤ N)이 하나 이상의 빈 칸을 사이에 두고 주어진다. 둘째 줄부터 N개의 줄에는 집의 좌표를 나타내는 xi (0 ≤ xi ≤ 1,000,000,000)가 한 줄에 하나씩 주어진다.

출력

첫째 줄에 가장 인접한 두 공유기 사이의 최대 거리를 출력한다.

 

예제입력1
5 3
1
2
8
4
9

예제출력1
3

 

N : 집의 개수 

C : 공유기 개수 

이후 집의 좌표 

 

N : 3, C: 3

집의 좌표를 먼저 오름차순으로 정렬한다.

1 2 4 8 9

5 3
1
2
8
4
9
i: 1 X[i] : 2 lo:1 hi : 8 mid: 4 start: 1 cnt :1
i: 2 X[i] : 4 lo:1 hi : 8 mid: 4 start: 1 cnt :1
i: 3 X[i] : 8 lo:1 hi : 8 mid: 4 start: 8 cnt :2
i: 4 X[i] : 9 lo:1 hi : 8 mid: 4 start: 8 cnt :2
i: 1 X[i] : 2 lo:1 hi : 3 mid: 2 start: 1 cnt :1
i: 2 X[i] : 4 lo:1 hi : 3 mid: 2 start: 4 cnt :2
i: 3 X[i] : 8 lo:1 hi : 3 mid: 2 start: 8 cnt :3
i: 4 X[i] : 9 lo:1 hi : 3 mid: 2 start: 8 cnt :3
i: 1 X[i] : 2 lo:3 hi : 3 mid: 3 start: 1 cnt :1
i: 2 X[i] : 4 lo:3 hi : 3 mid: 3 start: 4 cnt :2
i: 3 X[i] : 8 lo:3 hi : 3 mid: 3 start: 8 cnt :3
i: 4 X[i] : 9 lo:3 hi : 3 mid: 3 start: 8 cnt :3
3

 

/*[2110]공유기 설치*/
#include <bits/stdc++.h>
using namespace std;
#define MAXN ((int)2e5+10)
int N,C; //집의 개수, 공유기개수 
int X[MAXN];
long long M;

void InputData(){
    cin >> N >> C;
    for(int i =0; i<N; i++){
        cin >> X[i];
    }
}
void Solve(){
    int lo, hi, mid;
    long long sum;
    sort(X,X+N);
    lo = 1;
    hi = X[N-1] - X[0];
    int d = 0;
    int ans = 0;
    while(lo <= hi){
        mid=(lo+hi)/2; 
        int start = X[0];
        int cnt = 1;
        for(int i=1; i<N; i++){
            d = X[i] - start;
            if(mid <= d){
                ++cnt;
                start = X[i];
            }
       cout << "i: " << i << " X[i] : " << X[i] << " lo:" <<  lo  << " hi : " << hi  <<  " mid: " << mid <<  " start: " << start << " cnt :" << cnt  << endl;
         }
        if( cnt >= C){
            ans = mid;
            lo = mid + 1;
        }else{
            hi = mid - 1;
        }

        }
    cout << ans << endl;
}
int main(){
    InputData();
    Solve();
    return 0;
}
/*[2110]공유기 설치*/
반응형
반응형

문제

상근이는 나무 M미터가 필요하다. 근처에 나무를 구입할 곳이 모두 망해버렸기 때문에, 정부에 벌목 허가를 요청했다. 정부는 상근이네 집 근처의 나무 한 줄에 대한 벌목 허가를 내주었고, 상근이는 새로 구입한 목재절단기를 이용해서 나무를 구할것이다.

목재절단기는 다음과 같이 동작한다. 먼저, 상근이는 절단기에 높이 H를 지정해야 한다. 높이를 지정하면 톱날이 땅으로부터 H미터 위로 올라간다. 그 다음, 한 줄에 연속해있는 나무를 모두 절단해버린다. 따라서, 높이가 H보다 큰 나무는 H 위의 부분이 잘릴 것이고, 낮은 나무는 잘리지 않을 것이다. 예를 들어, 한 줄에 연속해있는 나무의 높이가 20, 15, 10, 17이라고 하자. 상근이가 높이를 15로 지정했다면, 나무를 자른 뒤의 높이는 15, 15, 10, 15가 될 것이고, 상근이는 길이가 5인 나무와 2인 나무를 들고 집에 갈 것이다. (총 7미터를 집에 들고 간다) 절단기에 설정할 수 있는 높이는 양의 정수 또는 0이다.

상근이는 환경에 매우 관심이 많기 때문에, 나무를 필요한 만큼만 집으로 가져가려고 한다. 이때, 적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최댓값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 나무의 수 N과 상근이가 집으로 가져가려고 하는 나무의 길이 M이 주어진다. (1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000)

둘째 줄에는 나무의 높이가 주어진다. 나무의 높이의 합은 항상 M보다 크거나 같기 때문에, 상근이는 집에 필요한 나무를 항상 가져갈 수 있다. 높이는 1,000,000,000보다 작거나 같은 양의 정수 또는 0이다.

 

출력

적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최댓값을 출력한다.

 

4 7
20 15 10 17
출력 : 15

5 20
4 42 40 26 46
출력:36

2 11
10 10
출력 : 4

3 1
1 2 2
출력 : 1
 
4 10
1 4 5 7
출력:2

5 2000000000
900000000 900000000 900000000 900000000 900000000
출력: 500000000

1 1000000000
1000000000
출력: 0

1 1
1000000000
출력: 999999999

6 12
19 9 18 20 17 8
출력: 15
 
5 14
4 22 10 16 36
출력: 22

풀이 과정 

나무수 N이 1,000,000개 이어서 이진 탐색으로 해서 찾아야 시간 초과 발생하지 않고 해결이 된다고 추측할 수 있다.

이진탐색색을 하기 위해서는 찾고자 하는 데이타를 오름차순 정렬을 해야 한다.

여기서 데이타는 나무 높이 데이타인 A를 정령해야 한다.

lo,hi값을 선정해야하는데, sorting후 제일 작은 값과 제일 큰 값으로 선정하면 된다. 

 

/*[2805]나무자르기*/
#include <bits/stdc++.h>
using namespace std;
#define MAXN ((int)1e6+10)
int N;
int A[MAXN +10];
long long M;

void Solve(){
    int lo, hi, mid,sol=0;
    long long sum;
    sort(A,A+N);
    lo = 1;
    hi = A[N-1];
    while(lo <= hi){
        sum=0;
        mid=(lo+hi)/2; 
        for(int i=0; i<N; i++){
            if(A[i] > mid) sum += (A[i] - mid);
        }
        if(sum >= M){
            sol=mid;
            lo=mid+1;
        }else{
           hi = mid-1; 
        }
    }
    cout << sol << endl;
}
void InputData(){
    cin >> N >> M;
    for(int i =0; i<N; i++){
        cin >> A[i];
    }
}
int main(){
    InputData();
    Solve();
    return 0;
}
/*[2805]나무자르기*/
반응형
반응형

문제

숫자 카드는 정수 하나가 적혀져 있는 카드이다. 상근이는 숫자 카드 N개를 가지고 있다. 정수 M개가 주어졌을 때, 이 수가 적혀있는 숫자 카드를 상근이가 몇 개 가지고 있는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다.

셋째 줄에는 M(1 ≤ M ≤ 500,000)이 주어진다. 넷째 줄에는 상근이가 몇 개 가지고 있는 숫자 카드인지 구해야 할 M개의 정수가 주어지며, 이 수는 공백으로 구분되어져 있다. 이 수도 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다.

출력

첫째 줄에 입력으로 주어진 M개의 수에 대해서, 각 수가 적힌 숫자 카드를 상근이가 몇 개 가지고 있는지를 공백으로 구분해 출력한다.

 

풀이

-오름차순 정렬

-이진 탐색

-Lowerbound

-Upperbound 

/*10816 숫자카드2*/
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN ((int)5e5+10) 
int N; 
int A[MAXN]; 
int M; 
int B[MAXN]; 
int Temp[MAXN];

void InputData() { 
    cin >> N;
    for(int i=0; i<N; i++) { 
        cin >> A[i]; 
    } 
    cin >> M;
    for(int i=0; i<M; i++) { 
        cin >> B[i]; 
    } 
} 
int BinarySearchLower(int s, int e, int d){
   int m, sol = -1;
    while( s <= e) {
        m = (s+e)/2;
        if( A[m] == d){
            sol = m;
            e = m -1;
        }
        else if (A[m] > d) e = m -1;
        else s = m+1;
    }
    return sol;
}

int BinarySearchUpper(int s, int e, int d){
    int m, sol = -1;
    while( s <= e) {
        m = (s+e) /2;
        if( A[m] == d){
            sol = m;
            s = m +1;
        }
        else if (A[m] > d) e = m -1;
        else s = m + 1;
    }
    return sol;
}

void Solve(){
    sort(A,A+N);
    for(int i=0; i<M; i++) { 
        int lower = BinarySearchLower(0, N-1, B[i] );
        if( lower != -1 ){
            int upper = BinarySearchUpper(0, N-1, B[i] );
            cout <<  upper - lower + 1 << ' '; 
        }else{
            cout <<  0 << ' '; 
        }
    } 
}
int main() { 
    InputData(); 
    Solve();
    return 0; 
} 
/*10816 숫자카드2*/
반응형
반응형

문제

N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들이 A안에 존재하는지 알아내면 된다. 모든 정수의 범위는 -231 보다 크거나 같고 231보다 작다.

출력

M개의 줄에 답을 출력한다. 존재하면 1을, 존재하지 않으면 0을 출력한다.

 

예제 입력 1 
5
4 1 5 2 3
5
1 3 7 9 5

예제 출력 1 
1
1
0
0
1

풀이

-오름차순 정렬

1 2 3 4 5

-숫자 1개씩 이진 탐색으로 검색 

중간 값을 구하기 위한 s,e값은 A[] array의 순서이다. 

if s = 0, e = N-1, d=1 부터 시작하면 

m = (s + e)/2; 

m = (0 + 4)/2=2;

A[2] =3이므로 

if(A[m] >d) 이므로 e=m-1로 값을 변경후 다시 찾는다.

s=0, e=1로 값 설정

 

m=(0+1)/2=0;

if(A[0]==d)에 부합하므로 값을 찾아서 return 1을 전달해 준다. 

/*[1920]수찾기*/
#include <bits/stdc++.h>
using namespace std;
#define MAXN ((int)1e6)
int N;
int A[MAXN +10];
int M;
int X[MAXN+10];

void InputData(){
    cin >> N;
    for(int i =0; i<N; i++){
        cin >> A[i];
    }
    cin >> M;
    for(int i=0; i<M; i++){
        cin >> X[i];
    }
}
bool BinarySearch(int s, int e, int d){
    int m;
    while(s<=e){
        m=(s+e)/2;
        if(A[m]==d) return 1;
        else if(A[m]>d) e=m-1;
        else s = m+1;
    }
    return 0;
}
void Solve(){
    sort(A,A+N);
    for(int i=0; i<M; i++){
        printf("%d\n", BinarySearch(0, N-1, X[i]));
    }
}
int main(){
    InputData();
    Solve();
    return 0;
}
/*[1920]수찾기*/

 

libray를 이용해서 풀이하면 아래와 같이 간단히 할 수 있다.

 

http://www.cplusplus.com/reference/algorithm/binary_search/

#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN ((int)1e6+10)
int N,M;
int A[MAXN],X[MAXN];
void Solve(){
    sort(A,A+N);
    for(int i=0; i<M; i++)
        cout<<binary_search(A, A+N, X[i])<<"\n";
}
void InputData(){
    cin >> N;
    for(int i =0; i<N; i++)
        cin >> A[i];
    cin >> M;
    for(int i=0; i<M; i++)
        cin >> X[i];
}
int main(){
    InputData();
    Solve();
    return 0;
}
반응형

+ Recent posts