[アルゴリズム]sds特別テーマ指導コード1


1713

#include <cstdio>

int n;  // 사진틀의 갯수  
int pic_frame[20]; // 사진틀(자료구조) 0 ~ 19 index를 갖는다 
int num_cc; // 추천갯수  
int ord_cc[1000]; // 추천 순서
int cand_like[101]; //후보 추천 횟수
int cand_where[101]; // 후보가 어떤 사진틀에 걸려있는 지 
int cand_when[101]; // 후보가 사진틀에 언제 올라갔는지 

int get_pic_frame() {
    // 잘 구현하는 것과
    // 조건을 찾다보면 뭔가 하나 빠져있음 변수가... 
    for (int i = 0 ; i < n ; i++) {
        if (pic_frame[i] == 0) return i;
    }

    // 올라가있는 후보중에서 좋아요가 가장 작은후보
    // 같으면 오래전에 올라간후보
    int res = 0;    // 최종 반환할 사진틀의 위치  
    int min_like = 1000;    // 올라간 후보중에서 좋아요가 가장 작은 값을 얻기 위한 값  
    int old_when = 1000;    // 올라간 시간이 가장 오래된 값을 찾기 위한 값
    for (int i = 0 ; i < n ; i++) {
        int cur = pic_frame[i];
        int tmp_like = cand_like[cur];
        int tmp_when = cand_when[cur];
        if (tmp_like < min_like) {
            min_like = tmp_like;
            old_when = tmp_when;
            res = i;
        }
        else if (tmp_like == min_like && tmp_when < old_when) {
            min_like = tmp_like;
            old_when = tmp_when;
            res = i;
        }
    }
    return res;
}

int main() {
    freopen("res/B1713.in", "r", stdin);
    scanf("%d", &n);
    scanf("%d", &num_cc);
    for (int i = 0 ; i < num_cc ; i++) {
        scanf("%d", &ord_cc[i]);
    }

    // 초기화 
    for (int i = 1 ; i <= 100 ; i++) {
        cand_where[i] = -1;
        cand_when[i] = -1;
    }

    // 추천을 수행한다 .... num_cc만큼
    for (int i = 0 ; i < num_cc ; i++) {
        // ord_cc[i]
        int cur = ord_cc[i];
        // 후보가 사진틀에 올라가 있을까?
        if (cand_where[cur] != -1) {
            // 좋아요만 올려줌 
            cand_like[cur]++;
        }
        else {
            // 비어있는 또는 후보를 넣을 사진틀을 얻는다. 
            int pos = get_pic_frame();
            int delete_cand = pic_frame[pos];
            // delete_cand는 사진틀에서 내리면서, 좋아요도 초기화한다
            if (delete_cand != 0) {
                cand_where[delete_cand] = -1;
                cand_like[delete_cand] = 0;
            }           
            cand_where[cur] = pos;
            cand_like[cur] = 1;
            cand_when[cur] = i;
            pic_frame[pos] = cur;
        }       
    }

    // 정답을 출력한다
    // pic_frame을 조사해서, 누가 사진틀에 있는지확인하고,
    // 후보들을 모아서 번호가 증가하는 순서대로 출력한다..
    for (int i = 1 ; i <= 100 ; i++) {
        if (cand_where[i] != -1) {
            printf("%d ", i);
        }
    }
}

1920

import java.io.*;
import java.util.*;

public class Main {
    private static int N;
    private static int M;
    private static int[] A;
    private static int[] Q;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        A = new int[N];

        st = new StringTokenizer(br.readLine());
        for (int i = 0 ; i < N ; i++) {
            A[i] = Integer.parseInt(st.nextToken());
        }

        st = new StringTokenizer(br.readLine());
        M = Integer.parseInt(st.nextToken());
        Q = new int[M];

        st = new StringTokenizer(br.readLine());
        for (int i = 0 ; i < M ; i++) {
            Q[i] = Integer.parseInt(st.nextToken());
        }

        // sorting
        Arrays.sort(A);
        // cpp
        // #include <algorithm>
        // sort(a, a + n);

        // binary search
        for (int i = 0 ; i < M ; i++) {
            System.out.println(binary_search(Q[i]));
        }
    }

    // 있으면 1
    // 없으면 0
    public static int binary_search(int key) {
        int left, right, mid;
        left = 0;
        right = N - 1;
        while (left <= right) {
            mid = (left + right) / 2;
            if (A[mid] == key) {
                return 1;
            }
            else if (key < A[mid]) {
                right = mid - 1;
            }
            else {
                left = mid + 1;
            }
        }
        return 0;
    }
}

1039

#include <cstdio>
#include <vector>
#include <queue> 
using namespace std;

int tonum(char arr[]) {
    int res = 0;
    for (int i = 0 ; arr[i] ; i++) {
        res *= 10;
        res += arr[i] - '0';
    }
    return res;
}

int conv(int num, int l, int r) {
    // l과 r의 체크가 안되어있음 
    // 처음에 num의 자리수는 정해져있기때문에 그걸 이용하면  됨 
    // arr
    char buf[16];
    sprintf(buf, "%d", num);
    char tmp;
    // swap
    tmp = buf[l];
    buf[l] = buf[r];
    buf[r] = tmp;
    // 앞자리가 0이 아닌지 체크도.. 
    if (buf[0] == '0') return 0;
    return tonum(buf);
}

int n, k;

bool isok(int num) {
    // 예외가 되는 것들은 바로처리  
    // 1 ~ 9 ==> 교환이 안됨 ==> -1
    if (num < 10) return false;
    // 10, 20, .. .90 ==> 교환이 안됨 ==> -1
    if (num < 100 && num % 10 == 0) return false;
    return true;
}

int get_num_len(int num) {
    int len = 0;
    while (num > 0) {
        len++;
        num /= 10;
    }
    return len;
}

int main() {    
    // todo - 완전탐색 
    // 숫자를 직접 교환하는 로직
    // 교환해서 단계별로 탐색해가는 로직 
    // 그리고 답 구하면 됨 
    scanf("%d%d", &n, &k);
    if (n == 1000000) {
        printf("%d", n);
        return 0;
    }
    if (!isok(n)) {
        printf("-1");
        return 0;
    }

    queue<int> q;
    q.push(n);
    for (int i = 0 ; i < k ; i++) {
        // q --> next_q --> q
        // 단계별로 처리하기 위해서 
        // 다음번 작업을 하기전에 임시로 저장하는 곳이고
        // q size를 이용해서 어찌어찌 처리를 하면 필요가 없어요 ==> 고민해보시면 됨
        vector<int> next_q;

        while (!q.empty()) {
            int cur = q.front();
            q.pop();
            int len = get_num_len(cur);

            for (int s = 0 ; s < len ; s++) {
                for (int e = s + 1 ; e < len ; e++) {
                    int next_num = conv(cur, s, e);
                    if (next_num == 0) continue;
                    // 꼭 다 넣어야할까???? 
                    // 현재 다음번 처리는 "중복"이 발생하고 있습니다 
                    // 적절하게 처리해 중복을 피해봅시다  
                    next_q.push_back(next_num);
                }
            }
        }

        for (int i = 0 ; i < next_q.size() ; i++) {
            q.push(next_q[i]);
        }
    }
    // k번을 돌렸기 때문에 q에남아 있는 것들은 k번을 수행하고 남은 숫자들이고
    // q에 남은것 중에 가장 큰것을 출력하면 됨
    int ans = 0;
    while (!q.empty()) {
        int cur = q.front();
        q.pop();
        if (ans < cur) ans = cur;
    }
    printf("%d", ans);
}

1759

import java.io.*;
import java.util.*;

public class Main {
    private static int L, C;
    private static char[] arr;
    private static char[] ans;

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());
        L = Integer.parseInt(st.nextToken());
        C = Integer.parseInt(st.nextToken());
        ans = new char[L];
        arr = new char[C];
        st = new StringTokenizer(br.readLine());
        for (int i = 0 ; i < C ; i++) {
            String str = st.nextToken();
            arr[i] = str.charAt(0);
        }
        Arrays.sort(arr);
        recur(0, 0);
    }

    public static void recur(int where, int from) {
        // final condition
        if (where == L) {
            if (check()) {
                System.out.println(new String(ans));
            }
            return;
        }
        for (int i = from ; i < C ; i++) {
            ans[where] = arr[i];
            // public static void recur(int where, int from)
            // 이 점에 미리 자음이랑 모음 개수를 세어놓을 수 있다.
            // 중간에 잘하면 가지치기도 가능
            recur(where + 1, i + 1);
        }
    }

    public static boolean check() {
        int countMoeum = 0, countJaeum = 0;
        boolean[] isMoeum = new boolean[128];
        isMoeum['a'] = true;
        isMoeum['e'] = true;
        isMoeum['i'] = true;
        isMoeum['o'] = true;
        isMoeum['u'] = true;
        for (int i = 0 ; i < L ; i++) {
            if (isMoeum[ans[i]]) countMoeum++;
            else countJaeum++;
        }
        return countMoeum >= 1 && countJaeum >= 2;
    }
}

1103

#include <cstdio>

int n, m, ans, dy[] = {-1, 1, 0, 0}, dx[] = {0, 0, -1, 1}, limit;
int max_count[50][50];  // 시작부터 가장 많이 점프 한 횟수 
char board[50][51];

void dfs(int y, int x, int cnt) {
    if (ans < cnt) ans = cnt;
    if (ans > limit) return;
    // 예외 처리
    if (y < 0 || n <= y || x < 0 || m <= x || board[y][x] == -1) return; 
    if (cnt <= max_count[y][x]) return;
    max_count[y][x] = cnt;
    int mul = board[y][x];
    for (int i = 0 ; i < 4 ; i++) {
        dfs(y + dy[i] * mul, x + dx[i] * mul, cnt + 1);
    }
}

int main() {
    scanf("%d%d", &n, &m);
    limit = n * m;
    for (int i = 0 ; i < n ; i++) {
        for (int j = 0 ; j < m ; j++) {
            // 처음 시작 점프 횟수가 0일 예정이라서 0보다 작은 -1로 초기화를 했는데,
            // 다른 방식으로도 구현이 가능합니다. 
            max_count[i][j] = -1;
        }
    }
    for (int i = 0 ; i < n ; i++) {
        scanf("%s", board[i]);
        for (int j = 0 ; j < m ; j++) {
            if (board[i][j] == 'H') board[i][j] = -1;
            else board[i][j] -= '0';
        }
    }
    dfs(0, 0, 0);
    if (ans > limit) ans = -1;
    printf("%d", ans); 
}

2580

#include <cstdio>
#include <vector>
using namespace std;

typedef pair<int, int> pii;

vector<pii> empty_space;
int sudoku[9][9]; 

// pos에 있는 empty_space를 어떤숫자로 채울지 판단 
void recur(int pos) {
    // final condition
    if (pos == empty_space.size()) {
        // 출력하고
        // 끝냄
        return; 
    }
    for (int i = 0 ; i <= 9 ; i++) {
    // 앞으로 할 일은 empty_space를 0 ~ 9 로 채워보는 건데
        // 언제채울 수 있냐면
        // 1. empty_space가 있는 작은 사각형에 숫자가 중복이 안될때!  ==> 그 작은 사각형을 어떻게 판단할지 
        // 2. empty_space가 있는 세로줄에 숫자가 중복이 안될때 ==> 세로줄을 어떻게 판단할지?? 
        // 3. empty_spcae가 있는 가로줄에 숫자가 중복이 안될때 ==> 가로줄을 어떻게 판단할지??? 
        // 1, 2, 3이 만족이 되면 일단 "그 숫자"로 채워보고
        recur(pos + 1);
        // 만약에 정답을 찾았으면 끝내는 방향으로 가고
        // 못찾았으면 다른 숫자로 채워보고... 
    }
}

int main() {

    // 입력을 받은 다음에
    // 빈 공간들("0")을 모은다 (y, x) --> empty_space

    // 모든 empty_space를 어떤 값으로 다 채웠다고 판단하면 그 상태가 정답이므로 출력을 한다. 
}

1339

#include <cstdio>
#include <vector>
using namespace std;

int n, alpha_cnt; // alpha_cnt : 서로다른 알파벳의 갯수 
int ans;
char word[10][10];
bool check[128];
bool used[10];

int mapping[10];
vector<char> alpha;
// mapping  0  1  2  3  4  5    ==> 순열로 나열할 것임 
// value    9  7  1  2  5  6
// alpha    Z  A  X  Y  D  E

// 알파벳에 매핑된 숫자를 반환 
int toNum(char c) {
    for (int i = 0 ; i < alpha_cnt ; i++) {
        if (alpha[i] == c) {
            return mapping[i];
        }
    }
    return 0;
}

// k번째 문자열을 숫자로 반환 
int getNum(int k) {
    int res = 0;
    //"ABCDE"
    //"98765"
    //9   98   987   9876  98765
    for (int i = 0 ; word[k][i] !=0 ; i++) {
        int num = toNum(word[k][i]);
        res *= 10, res += num;
    }
    return res;
}

int calc() {
    int sum = 0;
    for (int i = 0 ; i < n ; i++) {
        sum += getNum(i);
    }

    return sum;
}

// 매핑된 숫자로 뭔가 계산 
// 알파벳에 매핑할 숫자들 경우를 일이 구해보는 것 
void brute_force(int who) {
    // final condition
    if (who == alpha_cnt) {
        int tmp = calc();
        if (ans < tmp) {
            ans = tmp;
        }
        // debug
        /*
        for (int i = 0 ; i < alpha_cnt ; i++) {
            printf("%c ", alpha[i]);
        }
        printf("\n");
        for (int i = 0 ; i < alpha_cnt ; i++) {
            printf("%d ", mapping[i]);
        }
        printf("\n");
        printf("\n");
        */
        return;
    }
    for (int i = 0 ; i <= 9 ; i++) {
        if (used[i]) continue;
        used[i] = true;
        mapping[who] = i;
        brute_force(who + 1);
        mapping[who] = 0;   // 꼭 하지는 않아도 됨 
        used[i] = false;
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 0 ; i < n ; i++) {
        scanf("%s", word[i]);
        // 문자열 끝까지 읽는 다는 뜻(마지막 값은 0임 C++에서) 
        for (int j = 0 ; word[i][j] != 0 ; j++) {
            if (!check[word[i][j]]) {
                alpha_cnt++;
                check[word[i][j]] = true;
                alpha.push_back(word[i][j]);
            }
        }       
    }
    // 작업 - 숫자들을 하나씩 매핑 해보는 경우의 수
    brute_force(0);
    printf("%d", ans);
}

// 알파벳이 주어지면
// 알파벳별로 숫자를 하나씩 매핑해보는게 일입니다.
// 최대 10개가 주어지는데....경우의수?????
// 이렇게 만든 경우의수에 대해서
// 직접 숫자을 대입해서 합을구하고, 최대값을 찾는다.... 

// 두번째 ==> 숫자를 그대로이용하는 방법 
// ABCD : 1000 * A + 100 * B + 10 * C + D
// GCD : 100 * G + 10 * C + D
// EFABC : 10000 * E + 1000 * F + 100 * A + 10 * B + C
// ----------------------------------------------------
// 1100 * A + 110 * B + 21 * C + 2 * D + 10000 * E + 1000 * F + 100 * G

2003

import java.io.*;
import java.util.*;

public class Main {
    private static int N, M;
    private static int[] A;

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        A = new int[N];

        st = new StringTokenizer(br.readLine());
        for (int i = 0 ; i < N ; i++) {
            A[i] = Integer.parseInt(st.nextToken());
        }

        int answer = 0;
        // 완전탐색 비슷하게
        // 투포인터는??
        int s = 0, e = 0, sum = 0;
        for (s = 0 ; s < N ; s++) {
            for ( ; e < N ; e++) {
                sum += A[e];
                System.out.printf("[s ~ e] %d %d : %d\n", s, e, sum);
                if (sum == M) {
                    answer++;
                    break;
                }
                else if (sum > M) {
                    break;
                }
            }
            sum -= A[s];
        }       
        System.out.println(answer);
    }
}

2805

#include <cstdio>

typedef long long LL;

int n, m;
LL tree[1000000];
LL answer;

bool cutok(LL h) {
    LL sum = 0;
    for (int i = 0 ; i < n ; i++) {
        if (tree[i] > h) {
            sum += tree[i] - h;
        }
        if (sum >= m) return true; 
    }
    return false;
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0 ; i < n ; i++) {
        scanf("%lld", &tree[i]);
    }
    // 높이를 변경해가면서 나무를 잘라보고
    // 조건을 만족하는 가장 큰 높이를 찾아본다.....
    // 시간 초과가 발생할 것 같음
    /* 
    for (LL h = 0 ; h <= 1000000000 ; h++) {
        if (cutok(h)) {
            answer = h;
        }
        else {
            break;
        }
    }
    */
    LL bottom = 0, top = 1000000000, mid;
    while (bottom <= top) {
        mid = (bottom + top) / 2;
        if (cutok(mid)) {
            if (answer < mid) answer = mid;
            bottom = mid + 1;
        }
        else {
            top = mid - 1;
        }
    }
    printf("%lld", answer);
}

1072

import java.io.*;
import java.util.*;

public class Main {
    private static long X, Y, Z;    
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());
        X = Long.parseLong(st.nextToken());
        Y = Long.parseLong(st.nextToken());

        Z = Y * 100 / X;
        if (Z == 100 || Z == 99) {
            System.out.println(-1);
            return;
        }
        // 이분 탐색으로 진행
        long bottom = 1, top = 1000000000, mid;
        long answer = 1000000000;
        while (bottom <= top) {
            mid = (bottom + top) / 2;
            long nextZ = (Y + mid) * 100 / (X + mid);
            if (Z < nextZ) {
                if (mid < answer) {
                    answer = mid;
                }
                top = mid - 1;
            }
            else {
                bottom = mid + 1;
            }
        }
        System.out.println(answer);
        //System.out.println("Z : " + Z);
        //System.out.println("NEXT Z : " + (Y + answer) * 100 / (X + answer));
        /*
        // 경기횟수가 정수 범위를 벗어 난다면??????
        for (int i = 1 ; ; i++) {
            long nextZ = (Y + i) * 100 / (X + i);
            double tmp = (double)(Y + i) * 100 / (X + i);
            System.out.println(tmp);
            if (nextZ != Z) {
                System.out.println(i);
                break;
            }
        }
        */
    }   
}

7453

#include <cstdio>
#include <vector>
#include <algorithm> 
using namespace std;
typedef long long LL;

int n;
vector<int> a, b, c, d;
vector<int> ab, cd;

LL st1() {
    // 전략 1. 정렬 없이 바로 map 사용
}

LL st2_1() {
    // 전략 2. 정렬 ==>
    // 전략 2-1. lower_bound, upper_bound 
    sort(ab.begin(), ab.end());
    sort(cd.begin(), cd.end());
}

LL st2_2() {
    LL res = 0, cnt = 0;
    // 전략 2. 정렬 ==>
    // 전략 2-2. 안쓰고 ==> 
    sort(ab.begin(), ab.end());
    sort(cd.begin(), cd.end());
    int p_cd = cd.size() - 1;
    for (int p_ab = 0 ; p_ab < ab.size() ; p_ab++) {
        int target = -ab[p_ab];
        if (0 < p_ab && ab[p_ab] == ab[p_ab - 1]) {
            res += cnt;
        }
        else {
            while (0 <= p_cd && target < cd[p_cd]) {
                p_cd--;
            }
            cnt = 0;
            while (0 <= p_cd && target == cd[p_cd]) {
                cnt++;
                p_cd--
            }
            res += cnt;
        }
    }
    return res;
}

/*
LL st2_2() {
    LL res = 0, cnt = 0;
    // 전략 2. 정렬 ==>
    // 전략 2-2. 안쓰고 ==> 
    sort(ab.begin(), ab.end());
    sort(cd.begin(), cd.end());
    int p_cd = cd.size() - 1;
    for (int p_ab = 0 ; p_ab < ab.size() ; p_ab++) {
        if (0 < p_ab && ab[p_ab - 1] == ab[p_ab]) {
            res += cnt;
        }
        else {
            cnt = 0;
            while (0 <= p_cd && -ab[p_ab] < cd[p_cd]) p_cd--;
            while (0 <= p_cd && -ab[p_ab] == cd[p_cd]) cnt++, p_cd--;
            res += cnt; 
        }
    }
    return res;
}
*/

int main() {
    scanf("%d", &n);
    for (int i = 0 ; i < n ; i++) {
        int u, v, w, x;
        scanf("%d%d%d%d", &u, &v, &w, &x);
        a.push_back(u);
        b.push_back(v);
        c.push_back(w);
        d.push_back(x);
    }
    // a,b 로 만들수 있는 합의 조합 ==> ab
    // c,d로 만들수 있는 합의 조합 ==> cd
    for (int i = 0 ; i < n ; i++) {
        for (int j = 0 ; j < n ; j++) {
            ab.push_back(a[i] + b[j]);
            cd.push_back(c[i] + d[j]);
        }
    }

    //printf("%lld", st_1());
    //printf("%lld", st_2_1());
    printf("%lld", st2_2());
}

2842

#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

typedef pair<int, int> pii;

int n, h[50][50], dy[] = {-1, 1, 0, 0, -1, -1, 1, 1}, dx[] = {0, 0, -1, 1, -1, 1, -1, 1};
int cnt_k, y_post, x_post; 
char vil[50][51];
vector<int> hhh;

// low ~ high의 고도사이로 탐색을 했을때, 배달 할 수 있는 집의 개수를 리턴 
int bfs(int low, int high) {
    // to-do
    int cnt = 0;
    bool vt[50][50] = {false, };
    queue<pii> q;
    q.push(pii(y_post, x_post));
    vt[y_post][x_post] = true;
    if (h[y_post][x_post] < low || high < h[y_post][x_post]) return -1;
    while (!q.empty() && cnt < cnt_k) {
        pii cur = q.front();
        q.pop();
        for (int i = 0 ; i < 8 ; i++) {
            int nxty = cur.first + dy[i], nxtx = cur.second + dx[i];
            if (nxty < 0 || n <= nxty || nxtx < 0 || n <= nxtx) continue;
            if (vt[nxty][nxtx]) continue;
            if (h[nxty][nxtx] < low || high < h[nxty][nxtx]) continue;
            if (vil[nxty][nxtx] == 'K') {
                cnt++;
            }
            vt[nxty][nxtx] = true;
            q.push(pii(nxty, nxtx));
        }
    }

    return cnt;
}

// low ~ high의 고도사이로 탐색을 했을때, 배달 할 수 있는 집의 개수를 리턴 

//int dfs(int low, int high) {
//  // to-do
//}

int main() {
    freopen("res/B2842.in", "r", stdin);
    scanf("%d", &n);
    for (int i = 0 ; i < n ; i++) {
        scanf("%s", vil[i]);
    }
    for (int i = 0 ; i < n ; i++) {
        for (int j = 0 ; j < n ; j++) {
            if (vil[i][j] == 'K') {
                cnt_k++;
            }
            else if (vil[i][j] == 'P') {
                y_post = i, x_post = j;
            }
        }
    }
    for (int i = 0 ; i < n ; i++) {
        for (int j = 0 ; j < n ; j++) {
            scanf("%d", &h[i][j]);
            hhh.push_back(h[i][j]);
        }
    }
    // 하고 싶은 것
    // 낮은 높이, 높은 높이를 임의로 정해서 모든 집에 배달 할 수 있는지를 확인하고 싶다 

    //if (bfs(low, high) == cnt_k) ==> OK
    // low, high 모든 경우를 탐색하면 시간이 오래걸릴텐데......
    // 1. 이분 탐색을 이용 ==> hint : 특정 low에 대해서 되는 low + "a" 를 찾아보기
    // 2. 투포인터를 이용 ==> hint : 특정 시점에서 low-high가 만족을 했을때 다음 스텝은? 
    sort(hhh.begin(), hhh.end());
    int answer = hhh.back() - hhh[0];
    for (int low = 0, high = 0 ; low < hhh.size() && high < hhh.size() && low <= high ; ) {
        if (bfs(hhh[low], hhh[high]) == cnt_k) {
            int tmp = hhh[high] - hhh[low];
            if (tmp < answer) {
                answer = tmp;
            }
            low++;
        }
        else {
            high++;
        }
    }
    printf("%d", answer);
}

11003

#include <cstdio>
#include <deque>
using namespace std;

int n, l, a;
deque< pair<int, int> > q;
int main() {
    scanf("%d%d", &n, &l);
    for (int i = 0 ; i < n ; i++) {
        scanf("%d", &a);
        while (!q.empty()) {
            pair<int, int> t = q.back();
            if (t.second >= a) q.pop_back();
            else break;
        }
        q.push_back(make_pair(i, a));
        pair<int, int> t = q.front();
        if (t.first == i - l) q.pop_front(), t = q.front();
        printf("%d ", t.second);
    }
}

5639

import java.io.*;
import java.util.*;

public class Main {
    // file???
    // cpp cin.eof() == true
    // while (cin >> preorder[i++]);

    // scanf("%d", &a) == -1 끝
    // freopen("res/test.in", "r", stdin);
    private static int[] a = new int[10000];
    private static int sz;

    public static void main(String[] args) throws Exception {
        System.setIn(new FileInputStream("src/test.in"));

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str;
        while ((str = br.readLine()) != null) {
            a[sz] = Integer.parseInt(str.trim());
            sz++;
        }
        recur(0, sz - 1);
    }

    private static void recur(int s, int e) {
        // a[s] == 전위 순회에서는 root
        if (s == e) {
            System.out.println(a[s]);
            return;
        }
        else if (s > e) {
            return;
        }       
        else {
            int where = s + 1;
            while (where <= e) {
                if (a[where] > a[s]) break;
                else where++;
            }
            // left
            recur(s + 1, where - 1);
            // right
            recur(where, e);
            System.out.println(a[s]);
        }
    }
}

1655

#include <cstdio>
#include <queue>
#include <vector>
using namespace std;

priority_queue<int> max_pq;
priority_queue<int, vector<int>, greater<int>> min_pq;
int n;

int main() {
    freopen("res/B1655.in", "r", stdin);
    scanf("%d", &n);
    for (int i = 0 ; i < n ; i++) {
        int a;
        scanf("%d", &a);
        // processing 
        if (min_pq.size() == max_pq.size()) {
            // to max_pq
            max_pq.push(a);
        }
        else {
            // to min_pq
            min_pq.push(a);
        }
        if (!min_pq.empty() && !max_pq.empty() && min_pq.top() < max_pq.top()) {
            int min_value = min_pq.top();
            min_pq.pop();
            int max_value = max_pq.top();
            max_pq.pop();
            max_pq.push(min_value);
            min_pq.push(max_value);
        }
        //min_pq.top() < max_pq.top()   ==> 바꾼다.. 
        // print
        printf("%d\n", max_pq.top());
    }
}

3020

#include <cstdio>

int n, h, answer, count;
int seok[200000], jong[200000];

// x구간으로 날아갈때 k번째 석순과 만나는지 
bool check_seok(int k, int x) {
    if (x <= seok[k]) return true;
    return false;
}

// x구간으로 날아갈때 k번째 종유석과 만나는지 
bool check_jong(int k, int x) {
    if (h - jong[k] + 1 <= x) return true;
    return false;
}

int fly(int x) {
    int res = 0;
    for (int i = 0 ; i < n ; i += 2) {
        // 석순과 만나는지
        if (check_seok(i, x)) res++; 
        // 종유석과 만나는지 
        if (check_jong(i, x)) res++;
    }
    return res;
}

int main() {
    scanf("%d %d", &n, &h);
    for (int i = 0 ; i < n ; i += 2) {
        scanf("%d", &seok[i]);
        scanf("%d", &jong[i]);
    }
    answer = -1;
    for (int i = 1 ; i <= h ; i++) {
        int crash = fly(i);
        if (answer == -1 || crash < answer) {
            answer = crash;
            count = 1;
        }
        else if (crash == answer) {
            count++;
        }
    }
    printf("%d %d", answer, count);
}

1202

import java.io.*;
import java.util.*;

// "보석도둑"
public class Main {
    private static int N, K;
    private static long answer;
    //private static int[][] jewe;
    private static Info[] boseok;
    private static int[] gabang;

    public static void main(String[] args) throws Exception {       
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        boseok = new Info[N];
        gabang = new int[K];
        for (int i = 0 ; i < N ; i++) {
            st = new StringTokenizer(br.readLine());            
            int m = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            boseok[i] = new Info(m, v);
        }
        for (int i = 0 ; i < K ; i++) {
            st = new StringTokenizer(br.readLine());
            gabang[i] = Integer.parseInt(st.nextToken());
        }
        Arrays.sort(boseok, new Comparator<Info>() {
            @Override
            public int compare(Info arg0, Info arg1) {
                // int라서 이렇게 사용
                // long이면 직접 비교 수행하셔야합니다!
                return arg0.m - arg1.m;
            }
        });
        Arrays.sort(gabang);

        // 가방이 작은것 부터 무엇을 넣어야할지 판단해본다.
        int posBoseok = 0;
        //List<Integer> candBoseok = new ArrayList<Integer>; 너무 힘듬...매번정렬해야할지도...
        PriorityQueue<Integer> pq;  // 보석의 value를 넣을 것이다
        pq = new PriorityQueue<Integer>(new Comparator<Integer>() {
            @Override
            public int compare(Integer arg0, Integer arg1) {
                return arg1 - arg0;
            }
        });     
        for (int i = 0 ; i < K ; i++) {
            int curGabang = gabang[i];
            while (posBoseok < N && boseok[posBoseok].m <= curGabang) {
                pq.add(boseok[posBoseok].v);
                posBoseok++;
            }
            if (!pq.isEmpty()) {
                answer += pq.poll();
            }
//          // 보석 후보중에서 가장 가치가 높은것을 찾아서 answer +=
//          //for (int i = 0 ; i < candBoseok.size() ; i++) {
//              // find max

//          }
//          // ans++
//          // max 사용했다고 처리도 해야함..
        }
        System.out.println(answer);

    }
    static class Info {
        int m, v;
        Info (int m, int v) {
            this.m = m;
            this.v = v;
        }       
    }
}

2517

#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;

typedef pair<int, int> pii;

int n, num;
pii player[500000];
int tr[1<<20];

int seg_sum(int node, int s, int e, int l, int r) {
    if (r < s || e < l) return 0;
    if (l <= s && e <= r) {
        //return node; 틀림
        return tr[node];
    }
    else {
        return seg_sum(node * 2, s, (s + e) / 2, l, r) + seg_sum(node * 2 + 1, (s + e) / 2 + 1, e, l, r);
    }
}

void update(int node, int s, int e, int idx, int v) {
    if (idx < s || e < idx) return;
    if (s == e) {
        tr[node] = v;
        /*
        tr[node] += v;
        tr[node] -= v;
        tr[node] ^= v;
        tr[node] *= v;
        tr[node] &= v;
        */
    }
    else {
        update(node * 2, s, (s + e) / 2, idx, v);
        update(node * 2 + 1, (s + e) / 2 + 1, e, idx, v);
        tr[node] = tr[node * 2] + tr[node * 2 + 1];
    }
}

bool comp(pii p1, pii p2) {
    return p1.second < p2.second;
}

int main() {
    freopen("res/B2517.in", "r", stdin);
    scanf("%d", &n);
    for (int i = 0 ; i < n ; i++) {
        int power;
        scanf("%d", &power);
        player[i].first = i;
        player[i].second = power;
    }
    // sort power --> relabeling 
    sort(player, player + n, comp);

    for (int i = 0 ; i < n ; i++) {
        player[i].second = ++num;   // i + 1
    }

    // sort original order
    sort(player, player + n);
    for (int i = 0 ; i < n ; i++) {
        int curpower = player[i].second;
        int cnt = 0;
        if (curpower > 1) {
            cnt = seg_sum(1, 1, num, 1, curpower - 1);
        }
        update(1, 1, num, curpower, 1);
        printf("%d\n", i + 1 - cnt);
    }
}

11653

#include <cstdio>
#include <vector>
using namespace std;

bool che[3200];
vector<int> prime;
int n;

int main() {
    for (int i = 2 ; i < 3200 ; i++) {
        if (che[i]) continue;
        for (int j = i + i ; j < 3200 ; j += i) {
            che[j] = true;
        }
    }
    for (int i = 2 ; i < 3200 ; i++) {
        if (!che[i]) {
            prime.push_back(i);
        }
    }
    scanf("%d", &n);
    if (n == 1) {
        return 0;
    }
    for (int i = 0 ; i < prime.size() ; i++) {
        while (n % prime[i] == 0) {
            printf("%d\n", prime[i]);
            n /= prime[i];
        }
    }
    if (n > 1) {
        printf("%d\n", n);
    }
}

14476

import java.io.*;
import java.util.*;

public class Main {
    private static int N;
    private static int[] A;
    private static int[] leftGcd, rightGcd;
    private static int answer = -1, who;
    public static void main(String[] args) throws Exception {       
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());

        A = new int[N + 2];
        leftGcd = new int[N + 2];
        rightGcd = new int[N + 2];
        st = new StringTokenizer(br.readLine());
        for (int i = 1 ; i <= N ; i++) {
            A[i] = Integer.parseInt(st.nextToken());
        }
        for (int i = 1 ; i <= N ; i++) {
            leftGcd[i] = gcd(leftGcd[i - 1], A[i]);
        }
        for (int i = N ; i >= 1 ; i--) {
            rightGcd[i] = gcd(rightGcd[i + 1], A[i]);
        }
        for (int i = 1 ; i <= N ; i++) {
            int curGcd = gcd(leftGcd[i - 1], rightGcd[i + 1]);
            if (A[i] % curGcd == 0) continue;
            if (answer < curGcd) {
                answer = curGcd;
                who = A[i];
            }
        }
        if (answer == -1) {
            System.out.println(answer);
        }
        else {
            System.out.println(answer + " " + who);
        }
    }

    private static int gcd(int a, int b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

}

10610

#include <cstdio>

char s[100001];
int sum, count[128];

int main() {
    scanf("%s", s);
    for (int i = 0 ; s[i] ; i++) {
        sum += s[i] - '0';
        count[s[i]]++;
    }
    if (sum % 3 != 0 || count['0'] == 0) {
        printf("-1");
        return 0;
    }
    for (int i = '9' ; i >= '0' ; i--) {
        for (int j = 0 ; j < count[i] ; j++) {
            printf("%c", i);
        }
    }
}

2904

#include <cstdio>
#include <vector>
using namespace std;

bool che[1000001];
int n, a[100];
vector<int> prime;
int count[100][80000];  // 대략 100만 이하 소수가 7xxxx개 있는데..... 
int totalCount[80000];  // 전체 숫자에서 소수가 나타난 횟수 
int gcdCount[80000];    // gcd가 될 것 같은 횟수 
int answer1, answer2;   // 가장 큰 점수, 최소 횟수  

int main() {
    for (int i = 2 ; i <= 1000000 ; i++) {
        if (che[i]) continue;
        // i is prime 
        for (int j = i + i ; j <= 1000000 ; j += i) {
            che[j] = true;
        }
    }
    for (int i = 2 ; i <= 1000000 ; i++) {
        if (!che[i]) {
            prime.push_back(i);
        }
    }

    scanf("%d", &n);
    for (int i = 0 ; i < n ; i++) {
        scanf("%d", &a[i]);
    }

    // 각 숫자별로 소수가 몇개씩 있을까????? ==> 소인수분해 
    for (int i = 0 ; i < n ; i++) {
        int num = a[i];
        for (int j = 0 ; j < prime.size() ; j++) {
            while (num % prime[j] == 0) {
                count[i][j]++;
                totalCount[j]++;
                num /= prime[j];
            }
        }
    }
    for (int i = 0 ; i < prime.size() ; i++) {
        gcdCount[i] = totalCount[i] / n; 
    }
    answer1 = 1;
    for (int i = 0 ; i < prime.size() ; i++) {
        for (int j = 0 ; j < gcdCount[i] ; j++) {
            answer1 *= prime[i];
        }
        // 각 숫자들에 대해서 GCD되기 위해서 소수가 얼마나 부족한지 확인해본다 
        for (int j = 0 ; j < n ; j++) {
            if (count[j][i] < gcdCount[i]) {
                answer2 += gcdCount[i] - count[j][i];
            }
        }
    }
    printf("%d %d", answer1, answer2);

}

11051

#include <cstdio>

int cache[1001][1001];

int nCr(int n, int r) {
    if (r == 0) {
        return 1;
    }
    if (n < r) {
        return 0;
    }
    if (n < 0 || 1000 < n || r < 0 || 1000 < r) return 0;

    if (cache[n][r] != -1) {
        return cache[n][r];
    }

    int tmp = (nCr(n - 1, r - 1) + nCr(n - 1, r)) % 10007;
    cache[n][r] = tmp;
    return cache[n][r];
}

int main() {
    for (int i = 0 ; i <= 1000 ; i++) {
        for (int j = 0 ; j <= 1000 ; j++) {
            cache[i][j] = -1;
        }
    }
    int n, k;
    scanf("%d%d", &n, &k);
    printf("%d", nCr(n, k));
}

1256

import java.io.*;
import java.util.*;

public class Main {
    private static int N, M, K;
    private static int[][] cache;
    private static char[] answer;
    private static final int INF = 1000000010;

    public static void main(String[] args) throws Exception {       
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        cache = new int[101][101];
        for (int i = 0 ; i <= 100 ; i++) {
            for (int j = 0 ; j <= 100 ; j++) {
                cache[i][j] = -1;
            }
        }
        answer = new char[N + M];

        if (getAZ(N, M) < K) {
            System.out.println(-1);
            return;
        }

        // to-do
        // 가장 앞에 있는 문자열부터 채워 나간다
        int countA = N, countZ = M; // 앞으로 사용할 수 있는 문자

        for (int i = 0 ; i < N + M ; i++) {
            // i 번째 문자열이 a라면.....
            if (countA > 0) {
                int tmp = getAZ(countA - 1, countZ);
                if (tmp < K) {
                    answer[i] = 'z';
                    K -= tmp;
                    countZ--;
                }
                else {
                    answer[i] = 'a';
                    countA--;
                }
            }
            else {
                answer[i] = 'z';
            }
        }
        System.out.println(new String(answer));
    }

    public static int getAZ(int a, int z) {     
        if (a == 0 || z == 0) {
            return 1;
        }
        if (cache[a][z] != -1) {
            return cache[a][z];
        }
        cache[a][z] = getAZ(a - 1, z) + getAZ(a, z - 1);
        if (cache[a][z] >= INF) {
            cache[a][z] = INF;
        }
        return cache[a][z];
    }
}

15663

// 미완성
#include <cstdio>
#include <algorithm>
using namespace std;

int n, m, a[8], answer[8];
bool used[8];

void recur(int k) {
    if (k == m) {
        for (int i = 0 ; i < m ; i++) {
            printf("%d ", answer[i]);
        }
        printf("\n");
        return;
    }
    for (int i = 0 ; i < n ; i++) {
        if (used[i]) continue;
        used[i] = true;
        // hint...
        answer[k] = a[i];
        recur(k + 1);
        used[i] = false;
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0 ; i < n ; i++) scanf("%d", &a[i]);
    sort(a, a + n);
    recur(0);
}