ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 2428] 표절
    C 프로그래밍/BOJ 2022. 9. 2. 22:57
    728x90

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

     

    2428번: 표절

    첫째 줄에 제출한 솔루션의 개수 N이 주어진다. 둘째 줄에는 각 솔루션 파일의 크기 size(F1), size(F2), ..., size(FN)이 주어진다. (1 ≤ N ≤ 100,000, 1 ≤ size(Fi) ≤ 100,000,000) 솔루션 파일의 크기는 정수이

    www.acmicpc.net

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    int N;
    double files[100000 + 10];
    
    long long int cnt;
    
    void input(void)
    {
    	scanf("%d", &N);
    	for (int i = 0; i < N; i++) {
    		scanf("%lf", &files[i]);
    	}
    }
    
    int BS_lower(int start, int end, double target)	// 타겟보다 같거나 큰 값 중 가장 작은 값
    {
    	int s = start;
    	int e = end;
    	int pivot = 0;
    	int lb = -1;	// 하한을 찾지 못한 경우 예외처리 하기 위해 
    
    
    	while (s <= e) {
    		pivot = (s + e) / 2;
    
    		if (files[pivot] >= target) {
    			lb = pivot;	// 하한값의 후보들을 lb에 담는다. 
    			e = pivot - 1;	// 하한값의 후보들 중 가장 작은 값을 찾기 위함이다. 
    		}
    		else s = pivot + 1;
    	}
    	return lb;
    }
    
    
    int BS_upper(int start, int end, double target)	// 타겟보다 같거나 작은 값 중 가장 큰 값
    {
    	int s = start;
    	int e = end;
    	int pivot = 0;
    	int ub = -1;
    
    
    	while (s <= e) {
    		pivot = (s + e) / 2;
    
    		if (files[pivot] <= target) {
    			ub = pivot;	// 상한값의 후보들을 ub에 담는다. 
    			s = pivot + 1;	// 상한값의 후보들 중 가장 큰 값을 찾기 위함이다. 
    		}
    		else e = pivot - 1;
    	}
    	return ub;
    }
    
    
    
    void search_files(void)
    {
    	std::sort(files, files + N);	// 크기 기준 오름차순 정렬
    	
    	int lower = 0, upper = 0;
    	for (int i = N - 1; i > 0; i--) {	// 가장 크기가 큰 것 부터 탐색
    		double size = files[i] * 0.9;
    		lower = BS_lower(0, i - 1, size);
    		if (lower < 0) continue;
    		else {
    			upper = BS_upper(0, i - 1, files[i]);
    		}
    		cnt += (upper - lower + 1);
    		//printf("%d %d %d %d \n", i, lower, upper, cnt);
    	}
    }
    
    int main()
    {
    	input();
    	search_files();
    	printf("%lld", cnt);
    	return 0;
    }

    이 문제는 '제출한 파일의 개수가 너무 많다' 와 '파일 크기 너무 다른 경우에는 그러한 쌍을 검사하지 않고 넘어간다'는 문제의 설명을 보고, 파일 크기를 기준으로 오름차순 정렬 후 이분탐색으로 풀어야겠다고 생각했다. 

     

     

    // search_files( ) 함수

    #include <algorithm>으로 sort 라이브러리를 사용하여 입력받은 파일을 오름차순으로 정렬했다. 

    굳이 인덱스가 N - 1인 파일부터 탐색한 이유는, 문제에서의 부등식이 작은 파일의 범위를 나타내고 있기 때문이다. 즉, size(F_big) * 0.9 <= size(F_small) <= size(F_big) 과 같은 식을 도출할 수 있다. 따라서 해당 범위에 들어올 수 있는 작은 파일의 하한값과 상한값을 구하여 (upper - lower + 1) 을 해주면, 사이즈가 큰 파일(size(F_big))과 쌍을 이루어 검사할 수 있는 작은 파일들의 개수를 모두 구할 수 있다.

    한편, size = files[i] * 0.9 변수의 타입을 double로 놓은 이유는 * 0.9 때문이다. 이 때문에 files배열도 double로 선언하였다. 참고로 int로 하면 틀린다. (해봐서 앎 ㅋ)

     

     

    // BS_lower( ), BS_upper( ) 함수

    size(F_small) 의 하한값을 구할 때는 타겟을 size(F_big) * 0.9로 삼아, 배열의 원소들 중 해당 값보다 큰 수 중 가장 작은 것을 선택하기 위해 이분탐색한다. 

    size(F_small) 의 상한값을 구할 때는 타겟을 size(F_big)로 삼아, 배열의 원소들 중 해당 값보다 작은수 중 가장 큰 것을 선택하기 위해 이분탐색한다. 

     

    마지막으로, 검사하는 파일의 개수가 int 범위를 넘어갈 수 있다. 인풋받은 파일 100,000개의 크기가 모두 같은 경우 최대 10,000,000,000개를 검사해야 하기 때문에 cnt 변수를 long long int로 선언하고 "%lld"로 출력해야 한다.  

     

     

     

     

     

      

    728x90

    'C 프로그래밍 > BOJ' 카테고리의 다른 글

    [백준 3190] 뱀  (0) 2022.09.04
    [백준 10655] 마라톤1  (0) 2022.09.02
    [백준 2805] 나무 자르기  (0) 2022.09.01
    [백준 8983] 사냥꾼  (0) 2022.09.01
    [정올 2788] 도약  (0) 2022.09.01

    댓글

Designed by Tistory.