# 유형 : 투 포인터, 탐색

# 부분수열의 합 1(https://www.acmicpc.net/problem/1182) 에서는 2^20이어서 2초를 안넘겼지만, 이번 문제는 2^40이고 제한시간은 1초였다. 문제도 제대로 안읽고 1182번에서 푼 대로 접근해보았지만 당연히 시간초과.

어떻게 해결할지 생각해보다가 찾은 방법은 배열을 분할하여 푸는 방법이었다. 2^20은 약 1초만에 계산이 가능하기 때문에 가능한 방법.

[1,3,5,7,2,4,5,10] 을 [1,3,5,7] [2,4,5,10]으로 나누어 왼쪽의 부분집합의 합, 오른쪽의 부분집합의 합을 구하는 리스트를 구한 후, 정렬하여 투포인터 알고리즘을 사용하여 해결한다. 이 때 값들을 long 타입으로 안해줘서 74%정도에서 계속 틀렸습니다가 떠서 한참을 헤맸다.

 

1182번: 부분수열의 합

첫째 줄에 정수의 개수를 나타내는 N과 정수 S가 주어진다. (1 ≤ N ≤ 20, |S| ≤ 1,000,000) 둘째 줄에 N개의 정수가 빈 칸을 사이에 두고 주어진다. 주어지는 정수의 절댓값은 100,000을 넘지 않는다.

www.acmicpc.net

 

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

package bj;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.ArrayList;

import java.util.Collections;

import java.util.StringTokenizer;

 

public class p1208 {

    static int N,S;

    static int arr[];

    static ArrayList<Integer> left = new ArrayList<>();

    static ArrayList<Integer> right = new ArrayList<>();

    static long cnt=0;

    public static void main(String[] args) throws IOException {

        

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());

        S = Integer.parseInt(st.nextToken());

        arr = new int[N];

        

        st = new StringTokenizer(br.readLine());

        for(int i=0; i<N; i++)

            arr[i] = Integer.parseInt(st.nextToken());

        

        makeBinary(00, N/2, left);

        makeBinary(0, N/2, N, right);

        

        Collections.sort(left);

        Collections.sort(right);

        

        int leftIndex = 0;

        int rightIndex = right.size()-1;

        while(leftIndex<left.size() && rightIndex>=0) {

            long left_val = left.get(leftIndex);

            long right_val = right.get(rightIndex);

            

            if(left_val + right_val == S) {

                long left_count = 0;

                while(leftIndex<left.size() && left.get(leftIndex)==left_val) {

                    left_count++;

                    leftIndex++;

                }

                long right_count = 0;

                while(rightIndex >= 0 && right.get(rightIndex) == right_val) {

                    right_count++;

                    rightIndex--;

                }

                

                cnt += right_count * left_count;

            }

            

            if(left_val + right_val < S) {

                leftIndex++;

            }

            if(left_val + right_val > S) {

                rightIndex--;

            }

        }

        

        if(S==0)

            System.out.println(cnt-1);

        else

            System.out.println(cnt);

        

        

        

    }

    public static void makeBinary(int sum, int start, int end, ArrayList<Integer> list) {

        if(start >= end) {

            list.add(sum);

            return;

        }

        makeBinary(sum, start+1, end, list);

        makeBinary(sum+arr[start], start+1, end, list);

    }

}

 

Colored by Color Scripter

cs

'백준' 카테고리의 다른 글

#백준_1525 퍼즐 - Java  (0) 2020.01.21
#백준_7453 합이 0인 네 정수 - Java  (0) 2020.01.20
#백준_1261 알고스팟 - Java  (0) 2020.01.19
#백준_2261 가장 가까운 두 점  (0) 2020.01.13
#백준_1517 버블 소트  (0) 2020.01.13

유형 : 탐색, 다익스트라, 우선순위큐, BFS

# 푸는 방법 : 0인 곳으로 이동할 때는 dist를 증가시켜주지 않고, 1인곳으로 이동할 때는 dist를 증가시켜 주는데

두 정점을 구분하기 위해 탐색할때 다익스트라를 이용한 우선순위큐 또는 Deque를 사용한다.

 

1) Priority queue를 이용한 다익스트라

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

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.LinkedList;

import java.util.PriorityQueue;

import java.util.Queue;

import java.util.StringTokenizer;

 

public class Main {

    static int M,N;

    static int count=0;

    static int arr[][];

    static int dist[][];

    static boolean visit[][];

    static int moveX[] = {0,1,0,-1};

    static int moveY[] = {-1,0,1,0};

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine());

        M = Integer.parseInt(st.nextToken());

        N = Integer.parseInt(st.nextToken());

        

        arr = new int[N][M];

        visit = new boolean[N][M];

        dist = new int[N][M];

        

        for(int i=0; i<N; i++)

            for(int j=0; j<M; j++)

                dist[i][j] = Integer.MAX_VALUE;

        

        for(int i=0; i<N; i++) {

            String str = br.readLine();

            for(int j=0; j<M; j++) {

                arr[i][j] = str.charAt(j)-'0';

            }

        }

        bfs(new P(0,0,0));

        System.out.println(count);

    }

    

    public static void bfs(P p) {

        PriorityQueue<P> pq = new PriorityQueue<>();

        pq.add(p);

        int y = p.y;

        int x = p.x;

 

        dist[y][x] = 0;

        while(!pq.isEmpty()) {

            P tmp = pq.poll();

            x = tmp.x;

            y = tmp.y;

            int cnt = tmp.cnt;

 

//            System.out.println(y+" "+x+" "+cnt);

            if(x==M-1 && y==N-1) {

                count = cnt;

                return;

            }

            

            for(int d=0; d<4; d++) {

                

                int newX = x + moveX[d];

                int newY = y + moveY[d];

                

                if(0<=newX && newX<&& 0<=newY && newY<N) {

                    if(dist[newY][newX] > dist[y][x] + arr[newY][newX]) {

                        dist[newY][newX] = dist[y][x] + arr[newY][newX];

                        pq.add(new P(newX,newY,dist[y][x] + arr[newY][newX]));

                    }

                }

            }

        }

    }

    public static class P implements Comparable<P>{

        int x;

        int y;

        int cnt;

        public P(int x,int y,int cnt) {

            this.x=x;

            this.y=y;

            this.cnt=cnt;

        }

        @Override

        public int compareTo(P o) {

            // TODO Auto-generated method stub

            return this.cnt - o.cnt;

        }

    }

}

 

Colored by Color Scripter

cs

 

2) Deque를 이용한 방법

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

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

package bj;

 

import java.awt.Point;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.Deque;

import java.util.LinkedList;

import java.util.PriorityQueue;

import java.util.Queue;

import java.util.StringTokenizer;

 

public class p1261 {

    static int M,N;

    static int count=0;

    static int arr[][];

    static int dist[][];

    static boolean visit[][];

    static int moveX[] = {0,1,0,-1};

    static int moveY[] = {-1,0,1,0};

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine());

        M = Integer.parseInt(st.nextToken());

        N = Integer.parseInt(st.nextToken());

        

        arr = new int[N][M];

        visit = new boolean[N][M];

        dist = new int[N][M];

        

//        for(int i=0; i<N; i++)

//            for(int j=0; j<M; j++)

//                dist[i][j] = Integer.MAX_VALUE;

//        

        for(int i=0; i<N; i++) {

            String str = br.readLine();

            for(int j=0; j<M; j++) {

                arr[i][j] = str.charAt(j)-'0';

            }

        }

//        bfs(new P(0,0,0));

        bfs_usingDeque(new Point(0,0));

        System.out.println(dist[N-1][M-1]);

//        System.out.println(count);

    }

    public static void bfs_usingDeque(Point p) {

        Deque<Point> deque = new LinkedList<>();

        int x = p.x;

        int y = p.y;

        

        deque.addLast(p);

        while(!deque.isEmpty()) {

            Point tmp = deque.pollLast();

            x = tmp.x;

            y = tmp.y;

            

            for(int d=0; d<4; d++) {

                int newX = x + moveX[d];

                int newY = y + moveY[d];

                

                if(0<=newX && newX<&& 0<=newY && newY<&& !visit[newY][newX]) {

                    if(arr[newY][newX] == 0) {

                        dist[newY][newX] = dist[y][x];

                        deque.addLast(new Point(newX,newY));

                    }else {

                        dist[newY][newX] = dist[y][x] + 1;

                        deque.addFirst(new Point(newX,newY));

                    }

                    visit[newY][newX] = true;

                }

            }

        }

        

    }

    public static void bfs(P p) {

        PriorityQueue<P> pq = new PriorityQueue<>();

        pq.add(p);

        int y = p.y;

        int x = p.x;

 

        dist[y][x] = 0;

        while(!pq.isEmpty()) {

            P tmp = pq.poll();

            x = tmp.x;

            y = tmp.y;

            int cnt = tmp.cnt;

 

//            System.out.println(y+" "+x+" "+cnt);

            if(x==M-1 && y==N-1) {

                count = cnt;

                return;

            }

            

            for(int d=0; d<4; d++) {

                

                int newX = x + moveX[d];

                int newY = y + moveY[d];

                

                if(0<=newX && newX<&& 0<=newY && newY<N) {

                    if(dist[newY][newX] > dist[y][x] + arr[newY][newX]) {

                        dist[newY][newX] = dist[y][x] + arr[newY][newX];

                        pq.add(new P(newX,newY,dist[y][x] + arr[newY][newX]));

                    }

                }

            }

        }

    }

    public static class P implements Comparable<P>{

        int x;

        int y;

        int cnt;

        public P(int x,int y,int cnt) {

            this.x=x;

            this.y=y;

            this.cnt=cnt;

        }

        @Override

        public int compareTo(P o) {

            // TODO Auto-generated method stub

            return this.cnt - o.cnt;

        }

    }

}

 

Colored by Color Scripter

cs

'백준' 카테고리의 다른 글

#백준_7453 합이 0인 네 정수 - Java  (0) 2020.01.20
#백준_1208 부분수열의 합 2 - Java  (0) 2020.01.20
#백준_2261 가장 가까운 두 점  (0) 2020.01.13
#백준_1517 버블 소트  (0) 2020.01.13
#백준_11404 플로이드 - Java  (0) 2020.01.11

#유형 : 분할 정복 

# 간단한 알고리즘으로는 시간 초과를 벗어날 수 없음.. 풀었던 방법은

1) X좌표를 기준으로 정렬을 하여 middle index를 기준으로 왼쪽,오른쪽에서 가장 가까운 거리, middle 을 가로지르는 두 점간의 가장 가까운거리 3가지를 구해야 한다.

2) 왼쪽에서 가장 가까운 두점 사이의 거리, 오른쪽에서 가장 가까운 두점사이의 거리를 구하여 Min_value를 정해놓고, 이 값을 이용하여 middle index를 가로지르는 두 점간의 가장 가까운 거리를 구하여 min_value보다 작은 값들을 리스트에 넣는다.

3) 리스트를 Y좌표를 기준으로 정렬을 하여 y좌표들 간의 거리의 제곱이 stand보다 작은 값들만 거리를 구해서 비교하며 최솟값을 찾으면 된다.

 

 


package bj;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.StringTokenizer;

public class p2261 {
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(br.readLine());
		ArrayList arrList = new ArrayList<>();
		StringTokenizer st;
		for(int i=0; i<N; i++) {
			st = new StringTokenizer(br.readLine());
			int x = Integer.parseInt(st.nextToken());
			int y= Integer.parseInt(st.nextToken());
			arrList.add(new Point(x,y));
		}
		
		Collections.sort(arrList);
		System.out.println(solve(arrList, 0, N-1));
	}
	
	
	static int solve(ArrayList p, int x, int y) {
		int limit = y-x+1;
		
		if(limit<=3)
			return search(p, x, y);
		
		int middle = (x+y)/2;
		int left = solve(p, x, middle);
		int right = solve(p, middle+1, y);
		int stand = Math.min(left, right);
		
		ArrayList tmp = new ArrayList<>();
		for(int i=x; i<=y; i++) {
			int dist = p.get(i).x - p.get(middle).x;
			if(dist*dist < stand)
				tmp.add(p.get(i));
			
		}
		
		Collections.sort(tmp, new point_compartor());
		
		int size = tmp.size();
		for(int i=0; i<size-1; i++) {
			for(int j=i+1; j<size; j++) {
				int val = tmp.get(i).y - tmp.get(j).y;
				if(val*val < stand) {
					int d = getDistance(tmp.get(i), tmp.get(j));
					if(d < stand)
						stand = d;
				}else
					break;
			}
		}
		
		return stand;
	}
	public static int getDistance(Point p1, Point p2) {
		int result = (int) (Math.pow(p1.x-p2.x, 2) + Math.pow(p1.y - p2.y, 2));
		return result;
	}
	public static int search(ArrayList p, int x, int y) {
		int rs = -1;
		for(int i=x; i<=y-1; i++) {
			for(int j=i+1; j<=y; j++) {
				int val = getDistance(p.get(i), p.get(j));
				if(rs==-1 || rs>val)
					rs=val;
			}
		}
		return rs;
	}
	public static class Point implements Comparable{
		int x;
		int y;
		public Point(int x,int y) {
			this.x=x;
			this.y=y;
		}
		@Override
		public int compareTo(Point o) {
			int val = this.x - o.x;
			if(val == 0) {
				return this.y-o.y;
			}else
				return val;
		}
	}
	
	public static class point_compartor implements Comparator{

		@Override
		public int compare(Point o1, Point o2) {
			// TODO Auto-generated method stub
			return o1.y-o2.y;
		}
	}
}

# 유형 : 분할 정복, 정렬

# 제목은 버블 소트이지만, 버블 소트를 쓰면 바로 시간초과 남, 병합 정렬을 할 때 cnt를 세는 부분만 추가하면 된다. 카운트 증가는 병합 과정에서 왼쪽 값이 오른쪽 값 보다 클 때 왼쪽 배열에 있는 원소의 갯수만큼 계속 더해주면 된다.


package bj;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class p1517 {
	static long cnt=0;
	static long tmp[];
	static long arr[];
	
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(br.readLine());
		StringTokenizer st = new StringTokenizer(br.readLine());
		arr = new long[N];
		tmp = new long[N];
		for(int i=0; i<N; i++)
			arr[i] = Long.parseLong(st.nextToken());
		
		mergeSort(0, arr.length-1);
		System.out.println(cnt);
	}
	
	public static void mergeSort(int begin, int end) {
		if(begin<end) {
			int middle = (begin+end)/2;
			mergeSort(begin, middle);
			mergeSort(middle+1, end);
			merge(begin,middle,end);
		}
	}

	private static void merge(int begin, int middle, int end) {
		// TODO Auto-generated method stub
		int i = begin;
		int j = middle+1;
		int t = begin;
		
		while(i<=middle && j<=end) {
			if(arr[i] <= arr[j]) {
				tmp[t++] = arr[i++];
			}else {
				tmp[t++] = arr[j++];
				cnt +=  (middle + 1 - i);
			}
		}
		while(i<=middle)
			tmp[t++] = arr[i++];
		while(j<=end)
			tmp[t++] = arr[j++];
		
		for(int k=begin; k<=end; k++) {
			arr[k] = tmp[k];
		}
		
	}
}

# 유형 : 플로이드-와샬 알고리즘

# 플로이드 와샬 알고리즘을 알고 있다면 쉽게 풀 수 있는 문제

***시작 도시와 도착 도시를 연결하는 노선은 하나가 아닐 수 있다는 점만 유의할것


package bj;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class p11404 {
	static int INF = 1000000000;
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		int arr[][] = new int[n+1][n+1];
		for(int i=1; i<=n; i++) {
			for(int j=1; j<=n; j++) {
				if(i==j)
					continue;
				else
					arr[i][j] = INF;
			}
		}
		
		int m = Integer.parseInt(br.readLine());
		StringTokenizer st;
		for(int i=0; i<m; i++) {
			st = new StringTokenizer(br.readLine());
			int u = Integer.parseInt(st.nextToken());
			int v = Integer.parseInt(st.nextToken());
			int val = Integer.parseInt(st.nextToken());
			arr[u][v] = Math.min(arr[u][v], val);
		}
		
		for(int i=1; i<=n; i++) {
			for(int j=1; j<=n; j++) {
				for(int k=1; k<=n; k++) {
					arr[j][k] = Math.min(arr[j][k], arr[j][i] + arr[i][k]);
				}
			}
		}
		
		for(int i=1; i<=n; i++) {
			for(int j=1; j<=n; j++) {
				if(arr[i][j]>=INF)
					System.out.print("0 ");
				else
					System.out.print(arr[i][j]+ " ");
			}System.out.println();
		}
	}
}

# 유형 : 벨만포드

# 벨만포드 알고리즘을 알고 있다면 쉽게 해결이 가능하다. 중복되는 글이지만 https://ukyonge.tistory.com/26를 읽어 보는것도 추천한다.

# 주석 달아놓았음

 

 

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
package bj;
import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
 
public class p11657 {
    static int INF = 987654321;
    public static void main(String[] args) throws IOException {
        
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        
        Edge e[] = new Edge[M];
        
        long dist[] = new long[N+1];
        for(int i=1; i<=N; i++)
            dist[i] = INF;
        
        
        for(int i=0; i<M; i++) {
            st = new StringTokenizer(br.readLine());
            int u = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            int val = Integer.parseInt(st.nextToken());
            e[i] = new Edge(u,v,val);
        }
        
        dist[1= 0;
        //벨만포드 알고리즘은 다이나믹 프로그래밍 기반. 각 반복에 대하여 해당 정점과 연결되어 있는 모든 간선을 보아야한다. 따라서 시간복잡도는 O(|V||E|)
        // 경로의 길이는 N-1 이므로, 그 이상이 된다면 싸이클이 발생한다.
        for(int i=0; i<N-1; i++) {
            for(int j=0; j<M; j++) {
                if(dist[e[j].u] == INF) 
                    continue;
                // v로 가는 최단거리보다 dist[edge.u] + u에서 v로 가는 거리 가 더 짧을 때 갱신해준
                if(dist[e[j].v] > (dist[e[j].u] + e[j].val)) {
                    dist[e[j].v] = dist[e[j].u] + e[j].val;
                }
            }
        }
        
        // 음의 사이클 체크
        boolean check = false;
        for(int i=0; i<M; i++) {
            if(dist[e[i].u] != INF && dist[e[i].v] > dist[e[i].u] + e[i].val) {
                check = true;
                break;
            }
        }
        
        if(check)
            System.out.println(-1);
        else {
            for(int i=2; i<=N; i++) {
                if(dist[i] == INF)
                    System.out.println("-1");
                else
                    System.out.println(dist[i]);
            }
        }
        
    }
    
    public static class Edge{
        int u;
        int v;
        int val;
        public Edge(int u,int v, int val) {
            this.u = u;
            this.v = v;
            this.val = val;
        }
    }
}
 
cs

'백준' 카테고리의 다른 글

#백준_1517 버블 소트  (0) 2020.01.13
#백준_11404 플로이드 - Java  (0) 2020.01.11
#백준_1654 랜선 자르기 - Java  (0) 2020.01.11
#백준_2805 나무 자르기 - Java  (0) 2020.01.11
#백준_1992 쿼드트리 - Java  (0) 2020.01.11

# 분류 : 이진 탐색

# 최대 랜선 길이를 찾는 것이므로, count가 조건과 같다고 return 하여 문제를 접근하였으나 틀렸고 Count를 맞춰도 최대 길이를 찾아야 하기 때문에 추가적으로 left = Middle + 1 로 주어 진행하여야 한다. 단위가 크므로 long 타입을 쓰지 않으면 틀림


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int K = Integer.parseInt(st.nextToken());
		int N = Integer.parseInt(st.nextToken());
		
		int arr[] = new int[K];
		
		
		for(int i=0; i<K; i++)
			arr[i] = Integer.parseInt(br.readLine());
		
		Arrays.sort(arr);
		
		long left = 1;
		long right = arr[K-1];
		long middle=0;
		
		while(left<=right) {
			
			long cnt=0;
			
			middle = (left+right)/2;
			
			for(int i=0; i<K; i++) {
				cnt+= arr[i]/middle;
			}
			
			if(cnt < N) {
				right = middle-1;
			}else if(cnt >= N) {
				left = middle+1;
			}
		}
		System.out.println(right);
		
	}
}

# 분류 : 이진 탐색

# 정답률이 낮은데에 비해 쉽게 해결할 수 있던 문제, 어떠한 길이로 나무를 자를 때 음수가 되는 것만 주의하면 쉽게 해결


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int N = Integer.parseInt(st.nextToken());
		long M = Long.parseLong(st.nextToken());
		
		long arr[] = new long[N];
		st = new StringTokenizer(br.readLine());
		for(int i=0; i<N; i++) {
			arr[i] = Long.parseLong(st.nextToken());
		}
		
		Arrays.sort(arr);
		
		long left = 0;
		long right = 2000000000;
		
		while(left<=right) {
			long middle = (left+right)/2;
			
			long sum=0;
			for(int i=0; i<N; i++) {
				if((arr[i]-middle)<0) {
					sum+=0;
				}else
					sum+=arr[i]-middle;
			}
			if(sum < M) {
				right = middle-1;
			}else if(sum>=M)
				left = middle+1;
		}
		System.out.println(right);
	}
}

+ Recent posts